diff options
author | axis <qt-info@nokia.com> | 2009-04-24 11:34:15 (GMT) |
---|---|---|
committer | axis <qt-info@nokia.com> | 2009-04-24 11:34:15 (GMT) |
commit | 8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76 (patch) | |
tree | a17e1a767a89542ab59907462206d7dcf2e504b2 /src/tools/uic3 | |
download | Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.zip Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.tar.gz Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.tar.bz2 |
Long live Qt for S60!
Diffstat (limited to 'src/tools/uic3')
-rw-r--r-- | src/tools/uic3/converter.cpp | 1305 | ||||
-rw-r--r-- | src/tools/uic3/deps.cpp | 132 | ||||
-rw-r--r-- | src/tools/uic3/domtool.cpp | 587 | ||||
-rw-r--r-- | src/tools/uic3/domtool.h | 275 | ||||
-rw-r--r-- | src/tools/uic3/embed.cpp | 336 | ||||
-rw-r--r-- | src/tools/uic3/form.cpp | 921 | ||||
-rw-r--r-- | src/tools/uic3/main.cpp | 414 | ||||
-rw-r--r-- | src/tools/uic3/object.cpp | 66 | ||||
-rw-r--r-- | src/tools/uic3/parser.cpp | 85 | ||||
-rw-r--r-- | src/tools/uic3/parser.h | 57 | ||||
-rw-r--r-- | src/tools/uic3/qt3to4.cpp | 225 | ||||
-rw-r--r-- | src/tools/uic3/qt3to4.h | 82 | ||||
-rw-r--r-- | src/tools/uic3/subclassing.cpp | 362 | ||||
-rw-r--r-- | src/tools/uic3/ui3reader.cpp | 639 | ||||
-rw-r--r-- | src/tools/uic3/ui3reader.h | 233 | ||||
-rw-r--r-- | src/tools/uic3/uic.cpp | 341 | ||||
-rw-r--r-- | src/tools/uic3/uic.h | 142 | ||||
-rw-r--r-- | src/tools/uic3/uic3.pro | 43 | ||||
-rw-r--r-- | src/tools/uic3/widgetinfo.cpp | 285 | ||||
-rw-r--r-- | src/tools/uic3/widgetinfo.h | 77 |
20 files changed, 6607 insertions, 0 deletions
diff --git a/src/tools/uic3/converter.cpp b/src/tools/uic3/converter.cpp new file mode 100644 index 0000000..a5723dd --- /dev/null +++ b/src/tools/uic3/converter.cpp @@ -0,0 +1,1305 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "ui3reader.h" +#include "parser.h" +#include "domtool.h" +#include "ui4.h" +#include "widgetinfo.h" +#include "globaldefs.h" +#include "qt3to4.h" +#include "utils.h" +#include "option.h" +#include "cppextractimages.h" + +#include <QtDebug> +#include <QFile> +#include <QHash> +#include <QPair> +#include <QStringList> +#include <QDateTime> +#include <QRegExp> +#include <QSizePolicy> + +#include <stdio.h> +#include <stdlib.h> + +QT_BEGIN_NAMESPACE + +enum { warnHeaderGeneration = 0 }; + +#define CONVERT_PROPERTY(o, n) \ + do { \ + if (name == QLatin1String(o) \ + && !WidgetInfo::isValidProperty(className, (o)) \ + && WidgetInfo::isValidProperty(className, (n))) { \ + prop->setAttributeName((n)); \ + } \ + } while (0) + +static QString classNameForObjectName(const QDomElement &widget, const QString &objectName) +{ + QList<QDomElement> widgetStack; + widgetStack.append(widget); + while (!widgetStack.isEmpty()) { + QDomElement w = widgetStack.takeFirst(); + QDomElement child = w.firstChild().toElement(); + while (!child.isNull()) { + if (child.tagName() == QLatin1String("property") + && child.attribute(QLatin1String("name")) == QLatin1String("name")) { + QDomElement name = child.firstChild().toElement(); + DomString str; + str.read(name); + if (str.text() == objectName) + return w.attribute(QLatin1String("class")); + } else if (child.tagName() == QLatin1String("widget") + || child.tagName() == QLatin1String("vbox") + || child.tagName() == QLatin1String("hbox") + || child.tagName() == QLatin1String("grid")) { + widgetStack.prepend(child); + } + child = child.nextSibling().toElement(); + } + } + return QString(); +} + +// Check for potential KDE classes like +// K3ListView or KLineEdit as precise as possible +static inline bool isKDEClass(const QString &className) +{ + if (className.indexOf(QLatin1Char(':')) != -1) + return false; + const int size = className.size(); + if (size < 3 || className.at(0) != QLatin1Char('K')) + return false; + // K3ListView + if (className.at(1) == QLatin1Char('3')) { + if (size < 4) + return false; + return className.at(2).isUpper() && className.at(3).isLower(); + } + // KLineEdit + return className.at(1) .isUpper() && className.at(2).isLower(); +} + +DomUI *Ui3Reader::generateUi4(const QDomElement &widget, bool implicitIncludes) +{ + QDomNodeList nl; + candidateCustomWidgets.clear(); + + QString objClass = getClassName(widget); + if (objClass.isEmpty()) + return 0; + QString objName = getObjectName(widget); + + DomUI *ui = new DomUI; + ui->setAttributeVersion(QLatin1String("4.0")); + + QString pixmapFunction = QLatin1String("qPixmapFromMimeSource"); + QStringList ui_tabstops; + QStringList ui_custom_slots; + QList<DomInclude*> ui_includes; + QList<DomWidget*> ui_toolbars; + QList<DomWidget*> ui_menubars; + QList<DomAction*> ui_action_list; + QList<DomActionGroup*> ui_action_group_list; + QList<DomCustomWidget*> ui_customwidget_list; + QList<DomConnection*> ui_connection_list; + QList<QPair<int, int> > ui_connection_lineinfo_list; + QString author, comment, exportMacro; + QString klass; + + for (QDomElement n = root.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement()) { + QString tagName = n.tagName().toLower(); + + if (tagName == QLatin1String("tabstops")) { + QDomElement n2 = n.firstChild().toElement(); + while (!n2.isNull()) { + if (n2.tagName().toLower() == QLatin1String("tabstop")) { + QString name = n2.firstChild().toText().data(); + ui_tabstops.append(name); + } + n2 = n2.nextSibling().toElement(); + } + } else if (tagName == QLatin1String("pixmapfunction")) { + pixmapFunction = n.firstChild().toText().data(); + } else if (tagName == QLatin1String("class")) { + klass = n.firstChild().toText().data(); + } else if (tagName == QLatin1String("author")) { + author = n.firstChild().toText().data(); + } else if (tagName == QLatin1String("comment")) { + comment = n.firstChild().toText().data(); + } else if (tagName == QLatin1String("exportmacro")) { + exportMacro = n.firstChild().toText().data(); + } else if ( n.tagName() == QLatin1String("includehints") ) { + QDomElement n2 = n.firstChild().toElement(); + while ( !n2.isNull() ) { + if ( n2.tagName() == QLatin1String("includehint") ) { + QString name = n2.firstChild().toText().data(); + + DomInclude *incl = new DomInclude(); + incl->setText(fixHeaderName(name)); + incl->setAttributeLocation(n.attribute(QLatin1String("location"), QLatin1String("local"))); + ui_includes.append(incl); + } + n2 = n2.nextSibling().toElement(); + } + } else if (tagName == QLatin1String("includes")) { + QDomElement n2 = n.firstChild().toElement(); + while (!n2.isNull()) { + if (n2.tagName().toLower() == QLatin1String("include")) { + QString name = n2.firstChild().toText().data(); + if (n2.attribute(QLatin1String("impldecl"), QLatin1String("in implementation")) == QLatin1String("in declaration")) { + if (name.right(5) == QLatin1String(".ui.h")) + continue; + + DomInclude *incl = new DomInclude(); + incl->setText(fixHeaderName(name)); + incl->setAttributeLocation(n2.attribute(QLatin1String("location"), QLatin1String("global"))); + ui_includes.append(incl); + } + } + n2 = n2.nextSibling().toElement(); + } + } else if (tagName == QLatin1String("include")) { + QString name = n.firstChild().toText().data(); + if (n.attribute(QLatin1String("impldecl"), QLatin1String("in implementation")) == QLatin1String("in declaration")) { + if (name.right(5) == QLatin1String(".ui.h")) + continue; + + DomInclude *incl = new DomInclude(); + incl->setText(fixHeaderName(name)); + incl->setAttributeLocation(n.attribute(QLatin1String("location"), QLatin1String("global"))); + ui_includes.append(incl); + } + } else if (tagName == QLatin1String("layoutdefaults")) { + QString margin = n.attribute(QLatin1String("margin")); + QString spacing = n.attribute(QLatin1String("spacing")); + + DomLayoutDefault *layoutDefault = new DomLayoutDefault(); + + if (!margin.isEmpty()) + layoutDefault->setAttributeMargin(margin.toInt()); + + if (!spacing.isEmpty()) + layoutDefault->setAttributeSpacing(spacing.toInt()); + + ui->setElementLayoutDefault(layoutDefault); + } else if (tagName == QLatin1String("layoutfunctions")) { + QString margin = n.attribute(QLatin1String("margin")); + QString spacing = n.attribute(QLatin1String("spacing")); + + DomLayoutFunction *layoutDefault = new DomLayoutFunction(); + + if (!margin.isEmpty()) + layoutDefault->setAttributeMargin(margin); + + if (!spacing.isEmpty()) + layoutDefault->setAttributeSpacing(spacing); + + ui->setElementLayoutFunction(layoutDefault); + } else if (tagName == QLatin1String("images")) { + QDomNodeList nl = n.elementsByTagName(QLatin1String("image")); + QList<DomImage*> ui_image_list; + for (int i=0; i<(int)nl.length(); i++) { + QDomElement e = nl.item(i).toElement(); + + QDomElement tmp = e.firstChild().toElement(); + if (tmp.tagName().toLower() != QLatin1String("data")) + continue; + + // create the image + DomImage *img = new DomImage(); + img->setAttributeName(e.attribute(QLatin1String("name"))); + + // create the data + DomImageData *data = new DomImageData(); + img->setElementData(data); + + if (tmp.hasAttribute(QLatin1String("format"))) + data->setAttributeFormat(tmp.attribute(QLatin1String("format"), QLatin1String("PNG"))); + + if (tmp.hasAttribute(QLatin1String("length"))) + data->setAttributeLength(tmp.attribute(QLatin1String("length")).toInt()); + + data->setText(tmp.firstChild().toText().data()); + + ui_image_list.append(img); + QString format = img->elementData()->attributeFormat(); + QString extension = format.left(format.indexOf('.')).toLower(); + m_imageMap[img->attributeName()] = img->attributeName() + QLatin1Char('.') + extension; + } + + if (ui_image_list.size()) { + DomImages *images = new DomImages(); + images->setElementImage(ui_image_list); + ui->setElementImages(images); + } + } else if (tagName == QLatin1String("actions")) { + QDomElement n2 = n.firstChild().toElement(); + while (!n2.isNull()) { + QString tag = n2.tagName().toLower(); + + if (tag == QLatin1String("action")) { + DomAction *action = new DomAction(); + action->read(n2); + + QList<DomProperty*> properties = action->elementProperty(); + QString actionName = fixActionProperties(properties); + action->setAttributeName(actionName); + action->setElementProperty(properties); + + if (actionName.isEmpty()) { + delete action; + } else + ui_action_list.append(action); + } else if (tag == QLatin1String("actiongroup")) { + DomActionGroup *g= new DomActionGroup(); + g->read(n2); + + fixActionGroup(g); + ui_action_group_list.append(g); + } + n2 = n2.nextSibling().toElement(); + } + } else if (tagName == QLatin1String("toolbars")) { + QDomElement n2 = n.firstChild().toElement(); + while (!n2.isNull()) { + if (n2.tagName().toLower() == QLatin1String("toolbar")) { + DomWidget *tb = createWidget(n2, QLatin1String("QToolBar")); + ui_toolbars.append(tb); + } + n2 = n2.nextSibling().toElement(); + } + } else if (tagName == QLatin1String("menubar")) { + DomWidget *tb = createWidget(n, QLatin1String("QMenuBar")); + ui_menubars.append(tb); + } else if (tagName == QLatin1String("customwidgets")) { + QDomElement n2 = n.firstChild().toElement(); + while (!n2.isNull()) { + if (n2.tagName().toLower() == QLatin1String("customwidget")) { + + DomCustomWidget *customWidget = new DomCustomWidget; + customWidget->read(n2); + + if (!customWidget->hasElementExtends()) + customWidget->setElementExtends(QLatin1String("QWidget")); + + QDomElement n3 = n2.firstChild().toElement(); + QString cl; + + QList<DomPropertyData*> ui_property_list; + + while (!n3.isNull()) { + QString tagName = n3.tagName().toLower(); + + if (tagName == QLatin1String("property")) { + DomPropertyData *p = new DomPropertyData(); + p->read(n3); + + ui_property_list.append(p); + } + + n3 = n3.nextSibling().toElement(); + } + + if (ui_property_list.size()) { + DomProperties *properties = new DomProperties(); + properties->setElementProperty(ui_property_list); + customWidget->setElementProperties(properties); + } + + ui_customwidget_list.append(customWidget); + } + n2 = n2.nextSibling().toElement(); + } + } else if (tagName == QLatin1String("connections")) { + QDomElement n2 = n.firstChild().toElement(); + while (!n2.isNull()) { + if (n2.tagName().toLower() == QLatin1String("connection")) { + + DomConnection *connection = new DomConnection; + connection->read(n2); + + QString signal = fixMethod(connection->elementSignal()); + QString slot = fixMethod(connection->elementSlot()); + connection->setElementSignal(signal); + connection->setElementSlot(slot); + + ui_connection_list.append(connection); + ui_connection_lineinfo_list.append( + QPair<int, int>(n2.lineNumber(), n2.columnNumber())); + } + n2 = n2.nextSibling().toElement(); + } + } else if (tagName == QLatin1String("slots")) { + QDomElement n2 = n.firstChild().toElement(); + while (!n2.isNull()) { + if (n2.tagName().toLower() == QLatin1String("slot")) { + QString name = n2.firstChild().toText().data(); + ui_custom_slots.append(fixMethod(Parser::cleanArgs(name))); + } + n2 = n2.nextSibling().toElement(); + } + } + } + + // validate the connections + for (int i = 0; i < ui_connection_list.size(); ++i) { + DomConnection *conn = ui_connection_list.at(i); + QPair<int, int> lineinfo = ui_connection_lineinfo_list.at(i); + QString sender = conn->elementSender(); + QString senderClass = fixClassName(classNameForObjectName(widget, sender)); + QString signal = conn->elementSignal(); + QString receiver = conn->elementReceiver(); + QString receiverClass = fixClassName(classNameForObjectName(widget, receiver)); + QString slot = conn->elementSlot(); + + if (!WidgetInfo::isValidSignal(senderClass, signal)) { + errorInvalidSignal(signal, sender, senderClass, + lineinfo.first, lineinfo.second); + } else if (!WidgetInfo::isValidSlot(receiverClass, slot)) { + bool resolved = false; + if (objName == receiver) { + // see if it's a custom slot + foreach (QString cs, ui_custom_slots) { + if (cs == slot) { + resolved = true; + break; + } + } + } + if (!resolved) { + errorInvalidSlot(slot, receiver, receiverClass, + lineinfo.first, lineinfo.second); + } + } + } + + DomWidget *w = createWidget(widget); + Q_ASSERT(w != 0); + + QList<DomWidget*> l = w->elementWidget(); + l += ui_toolbars; + l += ui_menubars; + w->setElementWidget(l); + + if (ui_action_group_list.size()) + w->setElementActionGroup(ui_action_group_list); + + if (ui_action_list.size()) + w->setElementAction(ui_action_list); + + ui->setElementWidget(w); + + if (klass.isEmpty()) + klass = w->attributeName(); + + ui->setElementClass(klass); + ui->setElementAuthor(author); + ui->setElementComment(comment); + ui->setElementExportMacro(exportMacro); + + if (!ui->elementImages()) + ui->setElementPixmapFunction(pixmapFunction); + + for (int i=0; i<ui_customwidget_list.size(); ++i) { + const QString name = ui_customwidget_list.at(i)->elementClass(); + if (candidateCustomWidgets.contains(name)) + candidateCustomWidgets.remove(name); + } + + + QMapIterator<QString, bool> it(candidateCustomWidgets); + while (it.hasNext()) { + it.next(); + + const QString customClass = it.key(); + QString baseClass; + + if (customClass.endsWith(QLatin1String("ListView"))) + baseClass = QLatin1String("Q3ListView"); + else if (customClass.endsWith(QLatin1String("ListBox"))) + baseClass = QLatin1String("Q3ListBox"); + else if (customClass.endsWith(QLatin1String("IconView"))) + baseClass = QLatin1String("Q3IconView"); + else if (customClass.endsWith(QLatin1String("ComboBox"))) + baseClass = QLatin1String("QComboBox"); + + if (baseClass.isEmpty()) + continue; + + DomCustomWidget *customWidget = new DomCustomWidget(); + customWidget->setElementClass(customClass); + customWidget->setElementExtends(baseClass); + + // Magic header generation feature for legacy KDE forms + // (for example, filesharing/advanced/kcm_sambaconf/share.ui) + if (implicitIncludes && isKDEClass(customClass)) { + QString header = customClass.toLower(); + header += QLatin1String(".h"); + DomHeader *domHeader = new DomHeader; + domHeader->setText(header); + domHeader->setAttributeLocation(QLatin1String("global")); + customWidget->setElementHeader(domHeader); + if (warnHeaderGeneration) { + const QString msg = QString::fromUtf8("Warning: generated header '%1' for class '%2'.").arg(header).arg(customClass); + qWarning("%s", qPrintable(msg)); + } + } + ui_customwidget_list.append(customWidget); + } + + if (ui_customwidget_list.size()) { + DomCustomWidgets *customWidgets = new DomCustomWidgets(); + customWidgets->setElementCustomWidget(ui_customwidget_list); + ui->setElementCustomWidgets(customWidgets); + } + + if (ui_tabstops.size()) { + DomTabStops *tabStops = new DomTabStops(); + tabStops->setElementTabStop(ui_tabstops); + ui->setElementTabStops(tabStops); + } + + if (ui_includes.size()) { + DomIncludes *includes = new DomIncludes(); + includes->setElementInclude(ui_includes); + ui->setElementIncludes(includes); + } + + if (ui_connection_list.size()) { + DomConnections *connections = new DomConnections(); + connections->setElementConnection(ui_connection_list); + ui->setElementConnections(connections); + } + + ui->setAttributeStdSetDef(stdsetdef); + + if (m_extractImages) { + Option opt; + opt.extractImages = m_extractImages; + opt.qrcOutputFile = m_qrcOutputFile; + CPP::ExtractImages(opt).acceptUI(ui); + + ui->clearElementImages(); + + DomResources *res = ui->elementResources(); + if (!res) { + res = new DomResources(); + } + DomResource *incl = new DomResource(); + incl->setAttributeLocation(m_qrcOutputFile); + QList<DomResource *> inclList = res->elementInclude(); + inclList.append(incl); + res->setElementInclude(inclList); + if (!ui->elementResources()) + ui->setElementResources(res); + } + + return ui; +} + + + +QString Ui3Reader::fixActionProperties(QList<DomProperty*> &properties, + bool isActionGroup) +{ + QString objectName; + + QMutableListIterator<DomProperty*> it(properties); + while (it.hasNext()) { + DomProperty *prop = it.next(); + QString name = prop->attributeName(); + + if (name == QLatin1String("name")) { + objectName = prop->elementCstring(); + } else if (isActionGroup && name == QLatin1String("exclusive")) { + // continue + } else if (isActionGroup) { + errorInvalidProperty(name, objectName, isActionGroup ? QLatin1String("QActionGroup") : QLatin1String("QAction"), -1, -1); + delete prop; + it.remove(); + } else if (name == QLatin1String("menuText")) { + prop->setAttributeName(QLatin1String("text")); + } else if (name == QLatin1String("text")) { + prop->setAttributeName(QLatin1String("iconText")); + } else if (name == QLatin1String("iconSet")) { + prop->setAttributeName(QLatin1String("icon")); + } else if (name == QLatin1String("accel")) { + prop->setAttributeName(QLatin1String("shortcut")); + } else if (name == QLatin1String("toggleAction")) { + prop->setAttributeName(QLatin1String("checkable")); + } else if (name == QLatin1String("on")) { + prop->setAttributeName(QLatin1String("checked")); + } else if (!WidgetInfo::isValidProperty(QLatin1String("QAction"), name)) { + errorInvalidProperty(name, objectName, isActionGroup ? QLatin1String("QActionGroup") : QLatin1String("QAction"), -1, -1); + delete prop; + it.remove(); + } + } + + return objectName; +} + +void Ui3Reader::fixActionGroup(DomActionGroup *g) +{ + QList<DomActionGroup*> groups = g->elementActionGroup(); + for (int i=0; i<groups.size(); ++i) { + fixActionGroup(groups.at(i)); + } + + QList<DomAction*> actions = g->elementAction(); + for (int i=0; i<actions.size(); ++i) { + DomAction *a = actions.at(i); + + QList<DomProperty*> properties = a->elementProperty(); + QString name = fixActionProperties(properties); + a->setElementProperty(properties); + + if (name.size()) + a->setAttributeName(name); + } + + QList<DomProperty*> properties = g->elementProperty(); + QString name = fixActionProperties(properties, true); + g->setElementProperty(properties); + + if (name.size()) + g->setAttributeName(name); +} + +QString Ui3Reader::fixClassName(const QString &className) const +{ + return m_porting->renameClass(className); +} + +QString Ui3Reader::fixHeaderName(const QString &headerName) const +{ + return m_porting->renameHeader(headerName); +} + +DomWidget *Ui3Reader::createWidget(const QDomElement &w, const QString &widgetClass) +{ + DomWidget *ui_widget = new DomWidget; + + QString className = widgetClass; + if (className.isEmpty()) + className = w.attribute(QLatin1String("class")); + className = fixClassName(className); + + if ((className.endsWith(QLatin1String("ListView")) && className != QLatin1String("Q3ListView")) + || (className.endsWith(QLatin1String("ListBox")) && className != QLatin1String("Q3ListBox")) + || (className.endsWith(QLatin1String("ComboBox")) && className != QLatin1String("QComboBox")) + || (className.endsWith(QLatin1String("IconView")) && className != QLatin1String("Q3IconView"))) + candidateCustomWidgets.insert(className, true); + + bool isMenu = (className == QLatin1String("QMenuBar") || className == QLatin1String("QMenu")); + + ui_widget->setAttributeClass(className); + + QList<DomWidget*> ui_child_list; + QList<DomRow*> ui_row_list; + QList<DomColumn*> ui_column_list; + QList<DomItem*> ui_item_list; + QList<DomProperty*> ui_property_list; + QList<DomProperty*> ui_attribute_list; + QList<DomLayout*> ui_layout_list; + QList<DomActionRef*> ui_action_list; + QList<DomWidget*> ui_mainwindow_child_list; + + createProperties(w, &ui_property_list, className); + createAttributes(w, &ui_attribute_list, className); + + DomWidget *ui_mainWindow = 0; + DomWidget *ui_centralWidget = 0; + if (className == QLatin1String("QMainWindow") || className == QLatin1String("Q3MainWindow")) { + ui_centralWidget = new DomWidget; + ui_centralWidget->setAttributeClass(QLatin1String("QWidget")); + ui_mainwindow_child_list.append(ui_centralWidget); + ui_mainWindow = ui_widget; + } + + QDomElement e = w.firstChild().toElement(); + const bool inQ3ToolBar = className == QLatin1String("Q3ToolBar"); + while (!e.isNull()) { + QString t = e.tagName().toLower(); + if (t == QLatin1String("vbox") || t == QLatin1String("hbox") || t == QLatin1String("grid")) { + DomLayout *lay = createLayout(e); + Q_ASSERT(lay != 0); + + if (ui_layout_list.isEmpty()) { + ui_layout_list.append(lay); + } else { + // it's not possible to have more than one layout for widget! + delete lay; + } + } else if (t == QLatin1String("spacer")) { + // hmm, spacer as child of a widget.. it doesn't make sense, so skip it! + } else if (t == QLatin1String("widget")) { + DomWidget *ui_child = createWidget(e); + Q_ASSERT(ui_child != 0); + + bool isLayoutWidget = ui_child->attributeClass() == QLatin1String("QLayoutWidget"); + if (isLayoutWidget) + ui_child->setAttributeClass(QLatin1String("QWidget")); + + foreach (DomLayout *layout, ui_child->elementLayout()) { + fixLayoutMargin(layout); + } + + QString widgetClass = ui_child->attributeClass(); + if (widgetClass == QLatin1String("QMenuBar") || widgetClass == QLatin1String("QToolBar") + || widgetClass == QLatin1String("QStatusBar")) { + ui_mainwindow_child_list.append(ui_child); + } else { + ui_child_list.append(ui_child); + } + + if (inQ3ToolBar) { + DomActionRef *ui_action_ref = new DomActionRef(); + ui_action_ref->setAttributeName(ui_child->attributeName()); + ui_action_list.append(ui_action_ref); + } + } else if (t == QLatin1String("action")) { + DomActionRef *a = new DomActionRef(); + a->read(e); + ui_action_list.append(a); + } else if (t == QLatin1String("separator")) { + DomActionRef *a = new DomActionRef(); + a->setAttributeName(QLatin1String("separator")); + ui_action_list.append(a); + } else if (t == QLatin1String("property")) { + // skip the property it is already handled by createProperties + + QString name = e.attribute(QLatin1String("name")); // change the varname this widget + if (name == QLatin1String("name")) + ui_widget->setAttributeName(DomTool::readProperty(w, QLatin1String("name"), QVariant()).toString()); + } else if (t == QLatin1String("row")) { + DomRow *row = new DomRow(); + row->read(e); + ui_row_list.append(row); + } else if (t == QLatin1String("column")) { + DomColumn *column = new DomColumn(); + column->read(e); + ui_column_list.append(column); + } else if (isMenu && t == QLatin1String("item")) { + QString text = e.attribute(QLatin1String("text")); + QString name = e.attribute(QLatin1String("name")); + QString accel = e.attribute(QLatin1String("accel")); + + QList<DomProperty*> properties; + + DomProperty *atitle = new DomProperty(); + atitle->setAttributeName(QLatin1String("title")); + DomString *str = new DomString(); + str->setText(text); + atitle->setElementString(str); + properties.append(atitle); + + DomWidget *menu = createWidget(e, QLatin1String("QMenu")); + menu->setAttributeName(name); + menu->setElementProperty(properties); + ui_child_list.append(menu); + + DomActionRef *a = new DomActionRef(); + a->setAttributeName(name); + ui_action_list.append(a); + + } else if (t == QLatin1String("item")) { + DomItem *item = new DomItem(); + item->read(e); + ui_item_list.append(item); + } + + e = e.nextSibling().toElement(); + } + + ui_widget->setElementProperty(ui_property_list); + ui_widget->setElementAttribute(ui_attribute_list); + + if (ui_centralWidget != 0) { + Q_ASSERT(ui_mainWindow != 0); + ui_mainWindow->setElementWidget(ui_mainwindow_child_list); + ui_widget = ui_centralWidget; + } + + ui_widget->setElementWidget(ui_child_list); + ui_widget->setElementAddAction(ui_action_list); + ui_widget->setElementRow(ui_row_list); + ui_widget->setElementColumn(ui_column_list); + ui_widget->setElementItem(ui_item_list); + ui_widget->setElementLayout(ui_layout_list); + + //ui_widget->setAttributeName(p->elementCstring()); + + return ui_mainWindow ? ui_mainWindow : ui_widget; +} + +DomLayout *Ui3Reader::createLayout(const QDomElement &w) +{ + DomLayout *lay = new DomLayout(); + + QList<DomLayoutItem*> ui_item_list; + QList<DomProperty*> ui_property_list; + QList<DomProperty*> ui_attribute_list; + + QString tagName = w.tagName().toLower(); + + QString className; + if (tagName == QLatin1String("vbox")) + className = QLatin1String("QVBoxLayout"); + else if (tagName == QLatin1String("hbox")) + className = QLatin1String("QHBoxLayout"); + else + className = QLatin1String("QGridLayout"); + + lay->setAttributeClass(className); + + createProperties(w, &ui_property_list, className); + createAttributes(w, &ui_attribute_list, className); + + QDomElement e = w.firstChild().toElement(); + while (!e.isNull()) { + QString t = e.tagName().toLower(); + if (t == QLatin1String("vbox") + || t == QLatin1String("hbox") + || t == QLatin1String("grid") + || t == QLatin1String("spacer") + || t == QLatin1String("widget")) { + DomLayoutItem *lay_item = createLayoutItem(e); + Q_ASSERT(lay_item != 0); + ui_item_list.append(lay_item); + } + + e = e.nextSibling().toElement(); + } + + lay->setElementItem(ui_item_list); + lay->setElementProperty(ui_property_list); + lay->setElementAttribute(ui_attribute_list); + + return lay; +} + +DomLayoutItem *Ui3Reader::createLayoutItem(const QDomElement &e) +{ + DomLayoutItem *lay_item = new DomLayoutItem; + + QString tagName = e.tagName().toLower(); + if (tagName == QLatin1String("widget")) { + DomWidget *ui_widget = createWidget(e); + Q_ASSERT(ui_widget != 0); + + if (ui_widget->attributeClass() == QLatin1String("QLayoutWidget") + && ui_widget->elementLayout().size() == 1) { + QList<DomLayout*> layouts = ui_widget->elementLayout(); + + ui_widget->setElementLayout(QList<DomLayout*>()); + delete ui_widget; + + DomLayout *layout = layouts.first(); + fixLayoutMargin(layout); + lay_item->setElementLayout(layout); + } else { + if (ui_widget->attributeClass() == QLatin1String("QLayoutWidget")) + ui_widget->setAttributeClass(QLatin1String("QWidget")); + + lay_item->setElementWidget(ui_widget); + } + } else if (tagName == QLatin1String("spacer")) { + DomSpacer *ui_spacer = new DomSpacer(); + QList<DomProperty*> properties; + + QByteArray name = DomTool::readProperty(e, QLatin1String("name"), QLatin1String("spacer")).toByteArray(); + + Variant var; + var.createSize(0, 0); + + QVariant def = qVariantFromValue(var); + + Size size = asVariant(DomTool::readProperty(e, QLatin1String("sizeHint"), def)).size; + QString sizeType = QLatin1String("QSizePolicy::") + DomTool::readProperty(e, QLatin1String("sizeType"), QLatin1String("Expanding")).toString(); + QString orientation = QLatin1String("Qt::") + DomTool::readProperty(e, QLatin1String("orientation"), QLatin1String("Horizontal")).toString(); + + ui_spacer->setAttributeName(QLatin1String(name)); + + DomProperty *prop = 0; + + // sizeHint + prop = new DomProperty(); + prop->setAttributeName(QLatin1String("sizeHint")); + prop->setElementSize(new DomSize()); + prop->elementSize()->setElementWidth(size.width); + prop->elementSize()->setElementHeight(size.height); + properties.append(prop); + + // sizeType + prop = new DomProperty(); + prop->setAttributeName(QLatin1String("sizeType")); + prop->setElementEnum(sizeType); + properties.append(prop); + + // orientation + prop = new DomProperty(); + prop->setAttributeName(QLatin1String("orientation")); + prop->setElementEnum(orientation); + properties.append(prop); + + ui_spacer->setElementProperty(properties); + lay_item->setElementSpacer(ui_spacer); + } else { + DomLayout *ui_layout = createLayout(e); + Q_ASSERT(ui_layout != 0); + + fixLayoutMargin(ui_layout); + lay_item->setElementLayout(ui_layout); + } + + if (e.hasAttribute(QLatin1String("row"))) + lay_item->setAttributeRow(e.attribute(QLatin1String("row")).toInt()); + if (e.hasAttribute(QLatin1String("column"))) + lay_item->setAttributeColumn(e.attribute(QLatin1String("column")).toInt()); + if (e.hasAttribute(QLatin1String("rowspan"))) + lay_item->setAttributeRowSpan(e.attribute(QLatin1String("rowspan")).toInt()); + if (e.hasAttribute(QLatin1String("colspan"))) + lay_item->setAttributeColSpan(e.attribute(QLatin1String("colspan")).toInt()); + + return lay_item; +} + +void Ui3Reader::fixLayoutMargin(DomLayout *ui_layout) +{ + Q_UNUSED(ui_layout) +} + +static void addBooleanFontSubProperty(QDomDocument &doc, + const QString &name, const QString &value, + QDomElement &fontElement) +{ + if (value == QLatin1String("true") || value == QLatin1String("1")) { + QDomElement child = doc.createElement(name); + child.appendChild(doc.createTextNode(QLatin1String("true"))); + fontElement.appendChild(child); + } else { + if (value == QLatin1String("false") || value == QLatin1String("0")) { + QDomElement child = doc.createElement(name); + child.appendChild(doc.createTextNode(QLatin1String("false"))); + fontElement.appendChild(child); + } + } +} + +QDomElement Ui3Reader::findDerivedFontProperties(const QDomElement &n) const +{ + bool italic = false; + bool bold = false; + bool underline = false; + bool strikeout = false; + bool family = false; + bool pointsize = false; + + QDomDocument doc = n.ownerDocument(); + QDomElement result = doc.createElement(QLatin1String("font")); + + QDomNode pn = n.parentNode(); + while (!pn.isNull()) { + for (QDomElement e = pn.firstChild().toElement(); !e.isNull(); e = e.nextSibling().toElement()) { + if (e.tagName().toLower() == QLatin1String("property") && + e.attribute(QLatin1String("name")) == QLatin1String("font")) { + QDomElement f = e.firstChild().toElement(); + for (QDomElement fp = f.firstChild().toElement(); !fp.isNull(); fp = fp.nextSibling().toElement()) { + QString name = fp.tagName().toLower(); + QString text = fp.text(); + if (!italic && name == QLatin1String("italic")) { + italic = true; + addBooleanFontSubProperty(doc, name, text, result); + } else if (!bold && name == QLatin1String("bold")) { + bold = true; + addBooleanFontSubProperty(doc, name, text, result); + } else if (!underline && name == QLatin1String("underline")) { + underline = true; + addBooleanFontSubProperty(doc, name, text, result); + } else if (!strikeout && name == QLatin1String("strikeout")) { + strikeout = true; + addBooleanFontSubProperty(doc, name, text, result); + } else if (!family && name == QLatin1String("family")) { + family = true; + QDomElement child = doc.createElement(name); + child.appendChild(doc.createTextNode(text)); + result.appendChild(child); + } else if (!pointsize && name == QLatin1String("pointsize")) { + pointsize = true; + QDomElement child = doc.createElement(name); + child.appendChild(doc.createTextNode(text)); + result.appendChild(child); + } + } + } + } + pn = pn.parentNode(); + } + + return result; +} + +void Ui3Reader::createProperties(const QDomElement &n, QList<DomProperty*> *properties, + const QString &className) +{ + QString objectName; + + bool wordWrapFound = false; + + for (QDomElement e=n.firstChild().toElement(); !e.isNull(); e = e.nextSibling().toElement()) { + if (e.tagName().toLower() == QLatin1String("property")) { + QString name = e.attribute(QLatin1String("name")); + + // changes in QPalette + if (name == QLatin1String("colorGroup") + || name == QLatin1String("paletteForegroundColor") + || name == QLatin1String("paletteBackgroundColor") + || name == QLatin1String("backgroundMode") + || name == QLatin1String("backgroundOrigin") + || name == QLatin1String("paletteBackgroundPixmap") + || name == QLatin1String("backgroundBrush")) { + errorInvalidProperty(name, objectName, className, n.lineNumber(), n.columnNumber()); + continue; + } + + // changes in QFrame + if (name == QLatin1String("contentsRect")) { + errorInvalidProperty(name, objectName, className, n.lineNumber(), n.columnNumber()); + continue; + } + + // changes in QWidget + if (name == QLatin1String("underMouse") + || name == QLatin1String("ownFont")) { + errorInvalidProperty(name, objectName, className, n.lineNumber(), n.columnNumber()); + continue; + } + + if (name == QLatin1String("font")) { + QDomElement f = e.firstChild().toElement(); + e.appendChild(findDerivedFontProperties(f)); + e.removeChild(f); + } + + DomProperty *prop = readProperty(e); + if (!prop) + continue; + + if (prop->kind() == DomProperty::String) { + QDomNodeList comments = e.elementsByTagName(QLatin1String("comment")); + if (comments.length()) { + QString comment = comments.item(0).firstChild().toText().data(); + if (!comment.isEmpty()) + prop->elementString()->setAttributeComment(comment); + } + } + + // objectName + if (name == QLatin1String("name")) { + objectName = prop->elementCstring(); + continue; + } + + if (className == QLatin1String("Line") + && prop->attributeName() == QLatin1String("orientation")) { + delete prop; + continue; + } + + if (className.mid(1) == QLatin1String("LineEdit")) { + if (name == QLatin1String("hasMarkedText")) { + prop->setAttributeName(QLatin1String("hasSelectedText")); + } else if (name == QLatin1String("edited")) { + prop->setAttributeName(QLatin1String("modified")); + } else if (name == QLatin1String("markedText")) { + prop->setAttributeName(QLatin1String("selectedText")); + } + } + + if (className.endsWith(QLatin1String("ComboBox"))) { + CONVERT_PROPERTY(QLatin1String("currentItem"), QLatin1String("currentIndex")); + CONVERT_PROPERTY(QLatin1String("insertionPolicy"), QLatin1String("insertPolicy")); + } + + if (className == QLatin1String("QToolBar")) { + if (name == QLatin1String("label")) { + prop->setAttributeName(QLatin1String("windowTitle")); + } + } + + CONVERT_PROPERTY(QLatin1String("customWhatsThis"), QLatin1String("whatsThis")); + CONVERT_PROPERTY(QLatin1String("icon"), QLatin1String("windowIcon")); + CONVERT_PROPERTY(QLatin1String("iconText"), QLatin1String("windowIconText")); + CONVERT_PROPERTY(QLatin1String("caption"), QLatin1String("windowTitle")); + + if (name == QLatin1String("name")) { + continue; // skip the property name + } + + if (name == QLatin1String("accel")) { + prop->setAttributeName(QLatin1String("shortcut")); + } + + CONVERT_PROPERTY(QLatin1String("pixmap"), QLatin1String("icon")); + CONVERT_PROPERTY(QLatin1String("iconSet"), QLatin1String("icon")); + CONVERT_PROPERTY(QLatin1String("textLabel"), QLatin1String("text")); + + CONVERT_PROPERTY(QLatin1String("toggleButton"), QLatin1String("checkable")); + CONVERT_PROPERTY(QLatin1String("on"), QLatin1String("checked")); + + CONVERT_PROPERTY(QLatin1String("maxValue"), QLatin1String("maximum")); + CONVERT_PROPERTY(QLatin1String("minValue"), QLatin1String("minimum")); + CONVERT_PROPERTY(QLatin1String("lineStep"), QLatin1String("singleStep")); + + // QSlider + CONVERT_PROPERTY(QLatin1String("tickmarks"), QLatin1String("tickPosition")); + + name = prop->attributeName(); // sync the name + + if (className == QLatin1String("QLabel") && name == QLatin1String("alignment")) { + QString v = prop->elementSet(); + + if (v.contains(QRegExp(QLatin1String("\\bWordBreak\\b")))) + wordWrapFound = true; + } + + + // resolve the flags and enumerator + if (prop->kind() == DomProperty::Set) { + QStringList flags = prop->elementSet().split(QLatin1Char('|')); + QStringList v; + foreach (QString fl, flags) { + QString e = WidgetInfo::resolveEnumerator(className, fl); + if (e.isEmpty()) { + e = m_porting->renameEnumerator(className + QLatin1String("::") + fl); + } + + if (e.isEmpty()) { + fprintf(stderr, "uic3: flag '%s' for widget '%s' is not supported\n", fl.latin1(), className.latin1()); + continue; + } + + v.append(e); + } + + if (v.isEmpty()) { + delete prop; + continue; + } + + prop->setElementSet(v.join(QLatin1String("|"))); + } else if (prop->kind() == DomProperty::Enum) { + QString e = WidgetInfo::resolveEnumerator(className, prop->elementEnum()); + if (e.isEmpty()) { + e = m_porting->renameEnumerator(className + QLatin1String("::") + prop->elementEnum()); + } + + if (e.isEmpty()) { + fprintf(stderr, "uic3: enumerator '%s' for widget '%s' is not supported\n", + prop->elementEnum().latin1(), className.latin1()); + + delete prop; + continue; + } + prop->setElementEnum(e); + } + + + if (className.size() + && !(className == QLatin1String("QLabel") && name == QLatin1String("buddy")) + && !(name == QLatin1String("buttonGroupId")) + && !(name == QLatin1String("frameworkCode")) + && !(name == QLatin1String("database"))) { + if (!WidgetInfo::isValidProperty(className, name)) { + errorInvalidProperty(name, objectName, className, n.lineNumber(), n.columnNumber()); + delete prop; + } else { + properties->append(prop); + } + } else { + properties->append(prop); + } + } + } + if (className == QLatin1String("QLabel")) { + DomProperty *wordWrap = new DomProperty(); + wordWrap->setAttributeName(QLatin1String("wordWrap")); + if (wordWrapFound) + wordWrap->setElementBool(QLatin1String("true")); + else + wordWrap->setElementBool(QLatin1String("false")); + properties->append(wordWrap); + } +} + +static int toQt4SizePolicy(int qt3SizePolicy) +{ + if (qt3SizePolicy == 2) // qt 3 Ignored value + return QSizePolicy::Ignored; + return qt3SizePolicy; +} + +DomProperty *Ui3Reader::readProperty(const QDomElement &e) +{ + QString name = e.firstChild().toElement().tagName().toLower(); + + if (name == QLatin1String("class")) // skip class + name = e.firstChild().nextSibling().toElement().tagName().toLower(); + + DomProperty *p = new DomProperty; + p->read(e); + + if (p->kind() == DomProperty::Number) { + QString value = e.firstChild().toElement().firstChild().nodeValue(); + + if (value.contains(QLatin1Char('.'))) { + p->setElementDouble(value.toDouble()); + } + } else if (p->kind() == DomProperty::Pixmap) { + DomResourcePixmap *domPix = p->elementPixmap(); + if (m_extractImages) { + QString imageFile = domPix->text() + QLatin1String(".xpm"); + if (m_imageMap.contains(domPix->text())) + imageFile = m_imageMap.value(domPix->text()); + domPix->setAttributeResource(m_qrcOutputFile); + domPix->setText(QLatin1String(":/") + nameOfClass + QLatin1String("/images/") + imageFile); + } + } else if (p->kind() == DomProperty::SizePolicy) { + DomSizePolicy *sp = p->elementSizePolicy(); + if (sp) { + if (sp->hasElementHSizeType()) + sp->setElementHSizeType(toQt4SizePolicy(sp->elementHSizeType())); + if (sp->hasElementVSizeType()) + sp->setElementVSizeType(toQt4SizePolicy(sp->elementVSizeType())); + } + } else if (p->kind() == DomProperty::Unknown) { + delete p; + p = 0; + } + + return p; +} + +void Ui3Reader::createAttributes(const QDomElement &n, QList<DomProperty*> *properties, + const QString &className) +{ + Q_UNUSED(className); + + for (QDomElement e=n.firstChild().toElement(); !e.isNull(); e = e.nextSibling().toElement()) { + if (e.tagName().toLower() == QLatin1String("attribute")) { + QString name = e.attribute(QLatin1String("name")); + + DomProperty *prop = readProperty(e); + if (!prop) + continue; + + properties->append(prop); + } + } +} + +QString Ui3Reader::fixDeclaration(const QString &d) const +{ + QString text; + + int i = 0; + while (i < d.size()) { + QChar ch = d.at(i); + + if (ch.isLetter() || ch == QLatin1Char('_')) { + int start = i; + while (i < d.size() && (d.at(i).isLetterOrNumber() || d.at(i) == QLatin1Char('_'))) + ++i; + + text += fixClassName(d.mid(start, i-start)); + } else { + text += ch; + ++i; + } + } + + return text; +} + +/* + fixes a (possible composite) type name +*/ +QString Ui3Reader::fixType(const QString &t) const +{ + QString newText = t; + //split type name on <>*& and whitespace + QStringList typeNames = t.split(QRegExp(QLatin1String("<|>|\\*|&| ")), QString::SkipEmptyParts); + foreach(QString typeName , typeNames) { + QString newName = fixClassName(typeName); + if( newName != typeName ) { + newText.replace(typeName, newName); + } + } + return newText; +} + +QString Ui3Reader::fixMethod(const QString &method) const +{ + const QByteArray normalized = QMetaObject::normalizedSignature(method.toLatin1()); + QByteArray result; + int index = normalized.indexOf('('); + if (index == -1) + return QLatin1String(normalized); + result.append(normalized.left(++index)); + int limit = normalized.length()-1; + while (index < limit) { + QByteArray type; + while ((index < limit) && (normalized.at(index) != ',')) + type.append(normalized.at(index++)); + result.append(fixType(QLatin1String(type)).toLatin1()); + if ((index < limit) && (normalized.at(index) == ',')) + result.append(normalized.at(index++)); + } + result.append(normalized.mid(index)); + return QLatin1String(result); +} + +QT_END_NAMESPACE diff --git a/src/tools/uic3/deps.cpp b/src/tools/uic3/deps.cpp new file mode 100644 index 0000000..e621f25 --- /dev/null +++ b/src/tools/uic3/deps.cpp @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "ui3reader.h" + +#include <QDomElement> +#include <QFile> + +QT_BEGIN_NAMESPACE + +void Ui3Reader::computeDeps(const QDomElement &e, + QStringList &globalIncludes, + QStringList &localIncludes, bool impl) +{ + QDomNodeList nl; + + // additional includes (local or global) and forward declaractions + nl = e.toElement().elementsByTagName(QLatin1String("include")); + for (int i = 0; i < (int) nl.length(); i++) { + QDomElement n2 = nl.item(i).toElement(); + QString s = n2.firstChild().toText().data(); + + if (s.right(5) == QLatin1String(".ui.h") && !QFile::exists(s)) + continue; + + if (impl && n2.attribute(QLatin1String("impldecl"), QLatin1String("in implementation")) != QLatin1String("in implementation")) + continue; + + if (n2.attribute(QLatin1String("location")) != QLatin1String("local")) + globalIncludes += s; + else + localIncludes += s; + } + + // do the local includes afterwards, since global includes have priority on clashes + nl = e.toElement().elementsByTagName(QLatin1String("header")); + for (int i = 0; i < (int) nl.length(); i++) { + QDomElement n2 = nl.item(i).toElement(); + QString s = n2.firstChild().toText().data(); + if (n2.attribute(QLatin1String("location")) == QLatin1String("local") && !globalIncludes.contains(s)) { + if (s.right(5) == QLatin1String(".ui.h") && !QFile::exists(s)) + continue; + + if (impl && n2.attribute(QLatin1String("impldecl"), QLatin1String("in implementation")) != QLatin1String("in implementation")) + continue; + + localIncludes += s; + } + } + + // additional custom widget headers + nl = e.toElement().elementsByTagName(QLatin1String("header")); + for (int i = 0; i < (int) nl.length(); i++) { + QDomElement n2 = nl.item(i).toElement(); + QString s = n2.firstChild().toText().data(); + + if (n2.attribute(QLatin1String("location")) != QLatin1String("local")) + globalIncludes += s; + else + localIncludes += s; + } + + { // fix globalIncludes + globalIncludes = unique(globalIncludes); + QMutableStringListIterator it(globalIncludes); + while (it.hasNext()) { + QString v = it.next(); + + if (v.isEmpty()) { + it.remove(); + continue; + } + + it.setValue(fixHeaderName(v)); + } + } + + { // fix the localIncludes + localIncludes = unique(localIncludes); + QMutableStringListIterator it(localIncludes); + while (it.hasNext()) { + QString v = it.next(); + + if (v.isEmpty()) { + it.remove(); + continue; + } + + it.setValue(fixHeaderName(v)); + } + } +} + +QT_END_NAMESPACE diff --git a/src/tools/uic3/domtool.cpp b/src/tools/uic3/domtool.cpp new file mode 100644 index 0000000..ce2e2f6 --- /dev/null +++ b/src/tools/uic3/domtool.cpp @@ -0,0 +1,587 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "domtool.h" + +#include <QSizePolicy> +#include <QColor> +#include <QCursor> +#include <QDateTime> +#include <QRect> +#include <QSize> +#include <QFont> +#include <QDomElement> +#include <QByteArray> +#include <QtDebug> + +QT_BEGIN_NAMESPACE + +/* + \class DomTool + \brief The DomTool class provides static functions for Qt Designer + and uic. + + A collection of static functions used by Resource (part of the + designer) and Uic. + +*/ + +/* + Returns the contents of property \a name of object \a e as + a variant or the variant passed as \a defValue if the property does + not exist. The \a comment is passed on to the elementToVariant() + function. + + \sa hasProperty() +*/ +QVariant DomTool::readProperty(const QDomElement& e, const QString& name, const QVariant& defValue, QString& comment) +{ + QDomElement n; + for (n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement()) { + if (n.tagName() == QLatin1String("property")) { + if (n.attribute(QLatin1String("name")) != name) + continue; + return elementToVariant(n.firstChild().toElement(), defValue, comment); + } + } + return defValue; +} + + +/* + \overload + */ +QVariant DomTool::readProperty(const QDomElement& e, const QString& name, const QVariant& defValue) +{ + QString comment; + return readProperty(e, name, defValue, comment); +} + +/* + Returns whether object \a e defines property \a name or not. + + \sa readProperty() + */ +bool DomTool::hasProperty(const QDomElement& e, const QString& name) +{ + QDomElement n; + for (n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement()) { + if (n.tagName() == QLatin1String("property")) { + if (n.attribute(QLatin1String("name")) != name) + continue; + return true; + } + } + return false; +} + +/* + Returns a list of the names of the properties of the given \a type + found in the element \a e. +*/ +QStringList DomTool::propertiesOfType(const QDomElement& e, const QString& type) +{ + QStringList result; + QDomElement n; + for (n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement()) { + if (n.tagName() == QLatin1String("property")) { + QDomElement n2 = n.firstChild().toElement(); + if (n2.tagName() == type) + result += n.attribute(QLatin1String("name")); + } + } + return result; +} + + +/* + \overload +*/ +QVariant DomTool::elementToVariant(const QDomElement& e, const QVariant& defValue) +{ + QString dummy; + return elementToVariant(e, defValue, dummy); +} + +/* + Interprets element \a e as a variant and returns the result of the + interpretation, extracting the data as a text element is the \a + comment matches the tag name. If the interpretation fails the \a + defValue is returned instead. + */ +QVariant DomTool::elementToVariant(const QDomElement& e, const QVariant& defValue, QString &comment) +{ + Q_UNUSED(defValue); + + QVariant v; + Variant var; + + if (e.tagName() == QLatin1String("rect")) { + QDomElement n3 = e.firstChild().toElement(); + int x = 0, y = 0, w = 0, h = 0; + while (!n3.isNull()) { + if (n3.tagName() == QLatin1String("x")) + x = n3.firstChild().toText().data().toInt(); + else if (n3.tagName() == QLatin1String("y")) + y = n3.firstChild().toText().data().toInt(); + else if (n3.tagName() == QLatin1String("width")) + w = n3.firstChild().toText().data().toInt(); + else if (n3.tagName() == QLatin1String("height")) + h = n3.firstChild().toText().data().toInt(); + n3 = n3.nextSibling().toElement(); + } + var.createRect(x, y, w, h); + qVariantSetValue(v, var); + } else if (e.tagName() == QLatin1String("point")) { + QDomElement n3 = e.firstChild().toElement(); + int x = 0, y = 0; + while (!n3.isNull()) { + if (n3.tagName() == QLatin1String("x")) + x = n3.firstChild().toText().data().toInt(); + else if (n3.tagName() == QLatin1String("y")) + y = n3.firstChild().toText().data().toInt(); + n3 = n3.nextSibling().toElement(); + } + var.createPoint(x,y); + qVariantSetValue(v, var); + } else if (e.tagName() == QLatin1String("size")) { + QDomElement n3 = e.firstChild().toElement(); + int w = 0, h = 0; + while (!n3.isNull()) { + if (n3.tagName() == QLatin1String("width")) + w = n3.firstChild().toText().data().toInt(); + else if (n3.tagName() == QLatin1String("height")) + h = n3.firstChild().toText().data().toInt(); + n3 = n3.nextSibling().toElement(); + } + var.createSize(w, h); + qVariantSetValue(v, var); + } else if (e.tagName() == QLatin1String("color")) { + var.color = readColor(e); + qVariantSetValue(v, var); + } else if (e.tagName() == QLatin1String("font")) { + QDomElement n3 = e.firstChild().toElement(); + Font f; + f.init(); + while (!n3.isNull()) { + if (n3.tagName() == QLatin1String("family")) + f.family = qstrdup(n3.firstChild().toText().data().toLatin1()); + else if (n3.tagName() == QLatin1String("pointsize")) + f.pointsize = n3.firstChild().toText().data().toInt(); + else if (n3.tagName() == QLatin1String("bold")) + f.bold = n3.firstChild().toText().data().toInt(); + else if (n3.tagName() == QLatin1String("italic")) + f.italic = n3.firstChild().toText().data().toInt(); + else if (n3.tagName() == QLatin1String("underline")) + f.underline = n3.firstChild().toText().data().toInt(); + else if (n3.tagName() == QLatin1String("strikeout")) + f.strikeout = n3.firstChild().toText().data().toInt(); + n3 = n3.nextSibling().toElement(); + } + var.font = f; + qVariantSetValue(v, var); + } else if (e.tagName() == QLatin1String("string")) { + v = QVariant(e.firstChild().toText().data()); + QDomElement n = e; + n = n.nextSibling().toElement(); + if (n.tagName() == QLatin1String("comment")) + comment = n.firstChild().toText().data(); + } else if (e.tagName() == QLatin1String("cstring")) { + v = QVariant(e.firstChild().toText().data().toAscii()); + } else if (e.tagName() == QLatin1String("number")) { + bool ok = true; + v = QVariant(e.firstChild().toText().data().toInt(&ok)); + if (!ok) + v = QVariant(e.firstChild().toText().data().toDouble()); + } else if (e.tagName() == QLatin1String("bool")) { + QString t = e.firstChild().toText().data(); + v = QVariant(t == QLatin1String("true") || t == QLatin1String("1")); + } else if (e.tagName() == QLatin1String("pixmap")) { + v = QVariant(e.firstChild().toText().data()); + } else if (e.tagName() == QLatin1String("iconset")) { + v = QVariant(e.firstChild().toText().data()); + } else if (e.tagName() == QLatin1String("image")) { + v = QVariant(e.firstChild().toText().data()); + } else if (e.tagName() == QLatin1String("enum")) { + v = QVariant(e.firstChild().toText().data()); + } else if (e.tagName() == QLatin1String("set")) { + v = QVariant(e.firstChild().toText().data()); + } else if (e.tagName() == QLatin1String("sizepolicy")) { + QDomElement n3 = e.firstChild().toElement(); + var.createSizePolicy(); + while (!n3.isNull()) { + if (n3.tagName() == QLatin1String("hsizetype")) + var.sizePolicy.hsizetype = n3.firstChild().toText().data().toInt(); + else if (n3.tagName() == QLatin1String("vsizetype")) + var.sizePolicy.vsizetype = n3.firstChild().toText().data().toInt(); + else if (n3.tagName() == QLatin1String("horstretch")) + var.sizePolicy.horstretch = n3.firstChild().toText().data().toInt(); + else if (n3.tagName() == QLatin1String("verstretch")) + var.sizePolicy.verstretch = n3.firstChild().toText().data().toInt(); + n3 = n3.nextSibling().toElement(); + } + qVariantSetValue(v, var); + } else if (e.tagName() == QLatin1String("cursor")) { + var.createCursor(e.firstChild().toText().data().toInt()); + qVariantSetValue(v, var); + } else if (e.tagName() == QLatin1String("stringlist")) { + QStringList lst; + QDomElement n; + for (n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement()) + lst << n.firstChild().toText().data(); + v = QVariant(lst); + } else if (e.tagName() == QLatin1String("date")) { + QDomElement n3 = e.firstChild().toElement(); + int y, m, d; + y = m = d = 0; + while (!n3.isNull()) { + if (n3.tagName() == QLatin1String("year")) + y = n3.firstChild().toText().data().toInt(); + else if (n3.tagName() == QLatin1String("month")) + m = n3.firstChild().toText().data().toInt(); + else if (n3.tagName() == QLatin1String("day")) + d = n3.firstChild().toText().data().toInt(); + n3 = n3.nextSibling().toElement(); + } + v = QVariant(QDate(y, m, d)); + } else if (e.tagName() == QLatin1String("time")) { + QDomElement n3 = e.firstChild().toElement(); + int h, m, s; + h = m = s = 0; + while (!n3.isNull()) { + if (n3.tagName() == QLatin1String("hour")) + h = n3.firstChild().toText().data().toInt(); + else if (n3.tagName() == QLatin1String("minute")) + m = n3.firstChild().toText().data().toInt(); + else if (n3.tagName() == QLatin1String("second")) + s = n3.firstChild().toText().data().toInt(); + n3 = n3.nextSibling().toElement(); + } + v = QVariant(QTime(h, m, s)); + } else if (e.tagName() == QLatin1String("datetime")) { + QDomElement n3 = e.firstChild().toElement(); + int h, mi, s, y, mo, d ; + h = mi = s = y = mo = d = 0; + while (!n3.isNull()) { + if (n3.tagName() == QLatin1String("hour")) + h = n3.firstChild().toText().data().toInt(); + else if (n3.tagName() == QLatin1String("minute")) + mi = n3.firstChild().toText().data().toInt(); + else if (n3.tagName() == QLatin1String("second")) + s = n3.firstChild().toText().data().toInt(); + else if (n3.tagName() == QLatin1String("year")) + y = n3.firstChild().toText().data().toInt(); + else if (n3.tagName() == QLatin1String("month")) + mo = n3.firstChild().toText().data().toInt(); + else if (n3.tagName() == QLatin1String("day")) + d = n3.firstChild().toText().data().toInt(); + n3 = n3.nextSibling().toElement(); + } + v = QVariant(QDateTime(QDate(y, mo, d), QTime(h, mi, s))); + } + + return v; +} + + +/* Returns the color which is returned in the dom element \a e. + */ + +Color DomTool::readColor(const QDomElement &e) +{ + QDomElement n = e.firstChild().toElement(); + int r= 0, g = 0, b = 0; + while (!n.isNull()) { + if (n.tagName() == QLatin1String("red")) + r = n.firstChild().toText().data().toInt(); + else if (n.tagName() == QLatin1String("green")) + g = n.firstChild().toText().data().toInt(); + else if (n.tagName() == QLatin1String("blue")) + b = n.firstChild().toText().data().toInt(); + n = n.nextSibling().toElement(); + } + + Color c; + c.init(r, g, b); + return c; +} + +/* + Returns the contents of attribute \a name of object \a e as + a variant or the variant passed as \a defValue if the attribute does + not exist. The \a comment is passed to the elementToVariant() + function. + + \sa hasAttribute() + */ +QVariant DomTool::readAttribute(const QDomElement& e, const QString& name, const QVariant& defValue, QString& comment) +{ + QDomElement n; + for (n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement()) { + if (n.tagName() == QLatin1String("attribute")) { + if (n.attribute(QLatin1String("name")) != name) + continue; + return elementToVariant(n.firstChild().toElement(), defValue, comment); + } + } + return defValue; +} + +/* + \overload +*/ +QVariant DomTool::readAttribute(const QDomElement& e, const QString& name, const QVariant& defValue) +{ + QString comment; + return readAttribute(e, name, defValue, comment); +} + +/* + Returns whether object \a e defines attribute \a name or not. + + \sa readAttribute() + */ +bool DomTool::hasAttribute(const QDomElement& e, const QString& name) +{ + QDomElement n; + for (n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement()) { + if (n.tagName() == QLatin1String("attribute")) { + if (n.attribute(QLatin1String("name")) != name) + continue; + return true; + } + } + return false; +} + +static bool toBool(const QString& s) +{ + return s == QLatin1String("true") || s.toInt() != 0; +} + +static double versionToDouble(QString version) +{ + version = version.trimmed(); + + if (version.isEmpty()) + return 0.0; + + bool decpt = false; + QString num_str; + for (int i = 0; i < version.size(); ++i) { + char c = version.at(i).toAscii(); + if ((c < '0' || c > '9') && c != '.') + break; + if (c == '.') { + if (decpt) + break; + decpt = true; + } + num_str.append(QLatin1Char(c)); + } + + return num_str.toDouble(); +} + +/* + \internal + + Convert Qt 2.x format to Qt 3.x format if necessary. +*/ +void DomTool::fixDocument(QDomDocument& doc) +{ + QDomElement e; + QDomNode n; + QDomNodeList nl; + int i = 0; + + e = doc.firstChild().toElement(); + if (e.tagName() != QLatin1String("UI")) + return; + + // rename classes and properties + double version = versionToDouble(e.attribute(QLatin1String("version"))); + + nl = e.childNodes(); + fixAttributes(nl, version); + + // 3.x don't do anything more + if (version >= 3.0) + return; + + // in versions smaller than 3.0 we need to change more + + e.setAttribute(QLatin1String("version"), 3.0); + e.setAttribute(QLatin1String("stdsetdef"), 1); + nl = e.elementsByTagName(QLatin1String("property")); + for (i = 0; i < (int) nl.length(); i++) { + e = nl.item(i).toElement(); + QString name; + QDomElement n2 = e.firstChild().toElement(); + if (n2.tagName() == QLatin1String("name")) { + name = n2.firstChild().toText().data(); + if (name == QLatin1String("resizeable")) + e.setAttribute(QLatin1String("name"), QLatin1String("resizable")); + else + e.setAttribute(QLatin1String("name"), name); + e.removeChild(n2); + } + bool stdset = toBool(e.attribute(QLatin1String("stdset"))); + if (stdset || name == QLatin1String("toolTip") || name == QLatin1String("whatsThis") || + name == QLatin1String("buddy") || + e.parentNode().toElement().tagName() == QLatin1String("item") || + e.parentNode().toElement().tagName() == QLatin1String("spacer") || + e.parentNode().toElement().tagName() == QLatin1String("column") + ) + e.removeAttribute(QLatin1String("stdset")); + else + e.setAttribute(QLatin1String("stdset"), 0); + } + + nl = doc.elementsByTagName(QLatin1String("attribute")); + for (i = 0; i < (int) nl.length(); i++) { + e = nl.item(i).toElement(); + QString name; + QDomElement n2 = e.firstChild().toElement(); + if (n2.tagName() == QLatin1String("name")) { + name = n2.firstChild().toText().data(); + e.setAttribute(QLatin1String("name"), name); + e.removeChild(n2); + } + } + + nl = doc.elementsByTagName(QLatin1String("image")); + for (i = 0; i < (int) nl.length(); i++) { + e = nl.item(i).toElement(); + QString name; + QDomElement n2 = e.firstChild().toElement(); + if (n2.tagName() == QLatin1String("name")) { + name = n2.firstChild().toText().data(); + e.setAttribute(QLatin1String("name"), name); + e.removeChild(n2); + } + } + + nl = doc.elementsByTagName(QLatin1String("widget")); + for (i = 0; i < (int) nl.length(); i++) { + e = nl.item(i).toElement(); + QString name; + QDomElement n2 = e.firstChild().toElement(); + if (n2.tagName() == QLatin1String("class")) { + name = n2.firstChild().toText().data(); + e.setAttribute(QLatin1String("class"), name); + e.removeChild(n2); + } + } + +} + +struct widgetName { + widgetName(double v, QString b, QString a) + : version(v), before(b), after(a) {} + double version; + QString before; + QString after; +}; + +struct propertyName : public widgetName { + propertyName(double v, QString b, QString a, QString c = QString()) + : widgetName(v, b, a), clss(c) {} + QString clss; +}; + +const int widgs = 1; +widgetName widgetTable[1] = { + widgetName(3.3, QLatin1String("before"), QLatin1String("after")), +}; + +const int props = 1; +propertyName propertyTable[1] = { + propertyName(3.0, QLatin1String("resizeable"), QLatin1String("resizable")), // we need to fix a spelling error in 3.0 +}; + +/* + \internal +*/ +void DomTool::fixAttributes(QDomNodeList &nodes, double version) +{ + QDomNode n; + QDomNodeList nl; + for (int i = 0; i < (int) nodes.count(); ++i) { + n = nodes.item(i); + fixAttribute(n, version); + nl = n.childNodes(); + fixAttributes(nl, version); + } +} + +/* + \internal +*/ +void DomTool::fixAttribute(QDomNode &node, double version) +{ + QString tagName = node.toElement().tagName(); + if (tagName == QLatin1String("widget")) { + QString clss = node.toElement().attribute(QLatin1String("class")); + for (int i = 0; i < widgs; ++i) + if ((version < widgetTable[i].version) + && (clss == widgetTable[i].before)) { + node.toElement().setAttribute(QLatin1String("class"), propertyTable[i].after); + return; + } + return; + } + if (tagName == QLatin1String("property")) { + QDomElement e = node.parentNode().toElement(); + QString clss = e.attribute(QLatin1String("class")); + QString name = node.toElement().attribute(QLatin1String("name"), QLatin1String("")); + for (int i = 0; i < props; ++i) + if ((version < propertyTable[i].version) + && (clss == propertyTable[i].clss) + && (propertyTable[i].before.isNull() + || name == propertyTable[i].before)) { + node.toElement().setAttribute(QLatin1String("name"), propertyTable[i].after); + return; + } + } +} + +QT_END_NAMESPACE diff --git a/src/tools/uic3/domtool.h b/src/tools/uic3/domtool.h new file mode 100644 index 0000000..811c1f9 --- /dev/null +++ b/src/tools/uic3/domtool.h @@ -0,0 +1,275 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DOMTOOL_H +#define DOMTOOL_H + +#include <QVariant> + +QT_BEGIN_NAMESPACE + +class QDomElement; +class QDomDocument; +class QDomNode; +class QDomNodeList; + +struct Common +{ + int kind; + + enum { + Kind_Unknown = 0, + Kind_Color, + Kind_Point, + Kind_Size, + Kind_Rect, + Kind_Font, + Kind_SizePolicy, + Kind_Cursor + }; + + inline void init() + { kind = Kind_Unknown; } +}; + +struct Color +{ + Common common; + int red, green, blue; + + inline void init(int r, int g, int b) + { + common.kind = Common::Kind_Color; + red = r; + green = g; + blue = b; + } + + inline bool operator == (const Color &other) const + { return red == other.red && green == other.green && blue == other.blue; } +}; + +struct Point +{ + Common common; + int x, y; + + inline void init(int x, int y) + { + common.kind = Common::Kind_Point; + this->x = x; + this->y = y; + } +}; + +struct Size +{ + Common common; + int width, height; + + inline bool isNull() const + { return this->width == 0 && this->height == 0; } + + inline void init(int width, int height) + { + common.kind = Common::Kind_Size; + this->width = width; + this->height = height; + } +}; + +struct Rect +{ + Common common; + int x, y; + int width, height; + + inline void init(int x, int y, int width, int height) + { + common.kind = Common::Kind_Rect; + this->x = x; + this->y = y; + this->width = width; + this->height = height; + } +}; + +struct Font +{ + Common common; + char *family; + int pointsize; + bool bold; + bool italic; + bool underline; + bool strikeout; + + inline void init() + { + common.kind = Common::Kind_Font; + family = 0; + pointsize = 0; + bold = false; + italic = false; + underline = false; + strikeout = false; + } +}; + +struct SizePolicy +{ + Common common; + int hsizetype; + int vsizetype; + int horstretch; + int verstretch; + + inline void init() + { + common.kind = Common::Kind_SizePolicy; + hsizetype = 0; + vsizetype = 0; + horstretch = 0; + verstretch = 0; + } +}; + +struct Cursor +{ + Common common; + int shape; + + inline void init(int shape) + { + common.kind = Common::Kind_Cursor; + this->shape = shape; + } +}; + +union Variant +{ + Common common; + Color color; + Size size; + Point point; + Rect rect; + Font font; + SizePolicy sizePolicy; + Cursor cursor; + + inline Variant() + { common.kind = Common::Kind_Unknown; } + + inline ~Variant() + { + if (common.kind == Common::Kind_Font) { + delete[] font.family; + font.family = 0; + } + } + + inline int kind() const + { return common.kind; } + + inline Variant &createColor(int r, int g, int b) + { color.init(r, g, b); return *this; } + + inline Variant &createPoint(int x, int y) + { point.init(x, y); return *this; } + + inline Variant &createSize(int width, int height) + { size.init(width, height); return *this; } + + inline Variant &createRect(int x, int y, int w, int h) + { rect.init(x, y, w, h); return *this; } + + inline Variant &createFont() + { font.init(); return *this; } + + inline Variant &createSizePolicy() + { sizePolicy.init(); return *this; } + + inline Variant &createCursor(int shape) + { cursor.init(shape); return *this; } +}; + +class DomTool +{ +public: + static QVariant readProperty(const QDomElement& e, const QString& name, const QVariant& defValue); + static QVariant readProperty(const QDomElement& e, const QString& name, const QVariant& defValue, QString& comment); + static bool hasProperty(const QDomElement& e, const QString& name); + static QStringList propertiesOfType(const QDomElement& e, const QString& type); + static QVariant elementToVariant(const QDomElement& e, const QVariant& defValue); + static QVariant elementToVariant(const QDomElement& e, const QVariant& defValue, QString &comment); + static QVariant readAttribute(const QDomElement& e, const QString& name, const QVariant& defValue); + static QVariant readAttribute(const QDomElement& e, const QString& name, const QVariant& defValue, QString& comment); + static bool hasAttribute(const QDomElement& e, const QString& name); + static Color readColor(const QDomElement &e); + static void fixDocument(QDomDocument&); + static void fixAttributes(QDomNodeList&, double); + static void fixAttribute(QDomNode&, double); +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(Size) +Q_DECLARE_METATYPE(Rect) +Q_DECLARE_METATYPE(Font) +Q_DECLARE_METATYPE(SizePolicy) +Q_DECLARE_METATYPE(Cursor) +Q_DECLARE_METATYPE(Color) +Q_DECLARE_METATYPE(Point) +Q_DECLARE_METATYPE(Common) +Q_DECLARE_METATYPE(Variant) + +QT_BEGIN_NAMESPACE + +inline Variant asVariant(const QVariant &v) +{ + Variant var; + var = qVariantValue<Variant>(v); + return var; +} + +QT_END_NAMESPACE + +#endif // DOMTOOL_H diff --git a/src/tools/uic3/embed.cpp b/src/tools/uic3/embed.cpp new file mode 100644 index 0000000..882328a --- /dev/null +++ b/src/tools/uic3/embed.cpp @@ -0,0 +1,336 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "ui3reader.h" +#include <QFile> +#include <QImage> +#include <QStringList> +#include <QDateTime> +#include <QFileInfo> +#include <QVector> +#include <stdio.h> +#include <ctype.h> + +QT_BEGIN_NAMESPACE + +// on embedded, we do not compress image data. Rationale: by mapping +// the ready-only data directly into memory we are both faster and +// more memory efficient +#if defined(Q_WS_QWS) && !defined(QT_NO_IMAGE_COLLECTION_COMPRESSION) +# define QT_NO_IMAGE_COLLECTION_COMPRESSION +#elif defined (QT_NO_COMPRESS) +# define QT_NO_IMAGE_COLLECTION_COMPRESSION +#endif + +struct EmbedImage +{ + ~EmbedImage() { delete[] colorTable; } + + int width, height, depth; + int numColors; + QRgb* colorTable; + QString name; + QString cname; + bool alpha; +#ifndef QT_NO_IMAGE_COLLECTION_COMPRESSION + ulong compressed; +#endif +}; + +static QString convertToCIdentifier( const char *s ) +{ + QByteArray r = s; + int len = r.length(); + if ( len > 0 && !isalpha( (char)r[0] ) ) + r[0] = '_'; + for ( int i=1; i<len; i++ ) { + if ( !isalnum( (char)r[i] ) ) + r[i] = '_'; + } + + return QString::fromAscii(r); +} + + +static ulong embedData( QTextStream& out, const uchar* input, int nbytes ) +{ +#ifndef QT_NO_IMAGE_COLLECTION_COMPRESSION + QByteArray bazip( qCompress( input, nbytes ) ); + ulong len = bazip.size(); +#else + ulong len = nbytes; +#endif + static const char hexdigits[] = "0123456789abcdef"; + QString s; + for ( int i=0; i<(int)len; i++ ) { + if ( (i%14) == 0 ) { + s += QLatin1String("\n "); + out << s.latin1(); + s.truncate( 0 ); + } + uint v = (uchar) +#ifndef QT_NO_IMAGE_COLLECTION_COMPRESSION + bazip +#else + input +#endif + [i]; + s += QLatin1String("0x"); + s += QLatin1Char(hexdigits[(v >> 4) & 15]); + s += QLatin1Char(hexdigits[v & 15]); + if ( i < (int)len-1 ) + s += QLatin1Char(','); + } + if ( s.length() ) + out << s.latin1(); + return len; +} + +static void embedData( QTextStream& out, const QRgb* input, int n ) +{ + out << hex; + const QRgb *v = input; + for ( int i=0; i<n; i++ ) { + if ( (i%14) == 0 ) + out << "\n "; + out << "0x"; + out << hex << *v++; + if ( i < n-1 ) + out << ','; + } + out << dec; // back to decimal mode +} + +void Ui3Reader::embed(const char *project, const QStringList &images) +{ + + QString cProject = convertToCIdentifier( project ); + + QStringList::ConstIterator it; + out << "/****************************************************************************\n"; + out << "** Image collection for project '" << project << "'.\n"; + out << "**\n"; + out << "** Generated from reading image files: \n"; + for ( it = images.begin(); it != images.end(); ++it ) + out << "** " << *it << "\n"; + out << "**\n"; + out << "** Created: " << QDateTime::currentDateTime().toString() << "\n"; + out << "** by: The User Interface Compiler for Qt version " << QT_VERSION_STR << "\n"; + out << "**\n"; + out << "** WARNING! All changes made in this file will be lost!\n"; + out << "****************************************************************************/\n"; + out << "\n"; + + out << "#include <qimage.h>\n"; + out << "#include <qmime.h>\n"; + out << "#include <q3mimefactory.h>\n"; + out << "#include <q3dragobject.h>\n"; + out << "\n"; + + QList<EmbedImage*> list_image; + int image_count = 0; + for ( it = images.begin(); it != images.end(); ++it ) { + QImage img; + if ( !img.load( *it ) ) { + fprintf( stderr, "uic: cannot load image file %s\n", (*it).latin1() ); + continue; + } + EmbedImage *e = new EmbedImage; + e->width = img.width(); + e->height = img.height(); + e->depth = img.depth(); + e->numColors = img.numColors(); + e->colorTable = new QRgb[e->numColors]; + e->alpha = img.hasAlphaBuffer(); + QVector<QRgb> ct = img.colorTable(); + memcpy(e->colorTable, ct.constData(), e->numColors*sizeof(QRgb)); + QFileInfo fi( *it ); + e->name = fi.fileName(); + e->cname = QString::fromLatin1("image_%1").arg( image_count++); + list_image.append( e ); + out << "// " << *it << "\n"; + QString s; + if ( e->depth == 1 ) + img = img.convertBitOrder(QImage::BigEndian); + out << s.sprintf( "static const unsigned char %s_data[] = {", + e->cname.latin1() ); +#ifndef QT_NO_IMAGE_COLLECTION_COMPRESSION + e->compressed = +#endif + embedData( out, img.bits(), img.numBytes() ); + out << "\n};\n\n"; + if ( e->numColors ) { + out << s.sprintf( "static const QRgb %s_ctable[] = {", + e->cname.latin1() ); + embedData( out, e->colorTable, e->numColors ); + out << "\n};\n\n"; + } + } + + if ( !list_image.isEmpty() ) { + out << "static const struct EmbedImage {\n" + " int width, height, depth;\n" + " const unsigned char *data;\n" +#ifndef QT_NO_IMAGE_COLLECTION_COMPRESSION + " ulong compressed;\n" +#endif + " int numColors;\n" + " const QRgb *colorTable;\n" + " bool alpha;\n" + " const char *name;\n" + "} embed_image_vec[] = {\n"; + EmbedImage *e = 0; + int i; + for (i = 0; i < list_image.count(); ++i) { + e = list_image.at(i); + out << " { " + << e->width << ", " + << e->height << ", " + << e->depth << ", " + << "(const unsigned char*)" << e->cname << "_data, " +#ifndef QT_NO_IMAGE_COLLECTION_COMPRESSION + << e->compressed << ", " +#endif + << e->numColors << ", "; + if ( e->numColors ) + out << e->cname << "_ctable, "; + else + out << "0, "; + if ( e->alpha ) + out << "true, "; + else + out << "false, "; + out << "\"" << e->name << "\" },\n"; + delete e; + } +#ifndef QT_NO_IMAGE_COLLECTION_COMPRESSION + out << " { 0, 0, 0, 0, 0, 0, 0, 0, 0 }\n};\n"; +#else + out << " { 0, 0, 0, 0, 0, 0, 0, 0 }\n};\n"; +#endif + + out << "\n" + "static QImage uic_findImage( const QString& name )\n" + "{\n" + " for ( int i=0; embed_image_vec[i].data; i++ ) {\n" + " if ( QString::fromUtf8(embed_image_vec[i].name) == name ) {\n" +#ifndef QT_NO_IMAGE_COLLECTION_COMPRESSION + " QByteArray baunzip;\n" + " baunzip = qUncompress( embed_image_vec[i].data, \n" + " embed_image_vec[i].compressed );\n" + " QImage img((uchar*)baunzip.data(),\n" + " embed_image_vec[i].width,\n" + " embed_image_vec[i].height,\n" + " embed_image_vec[i].depth,\n" + " (QRgb*)embed_image_vec[i].colorTable,\n" + " embed_image_vec[i].numColors,\n" + " QImage::BigEndian\n" + " );\n" + " img = img.copy();\n" +#else + " QImage img((uchar*)embed_image_vec[i].data,\n" + " embed_image_vec[i].width,\n" + " embed_image_vec[i].height,\n" + " embed_image_vec[i].depth,\n" + " (QRgb*)embed_image_vec[i].colorTable,\n" + " embed_image_vec[i].numColors,\n" + " QImage::BigEndian\n" + " );\n" +#endif + " if ( embed_image_vec[i].alpha )\n" + " img.setAlphaBuffer(true);\n" + " return img;\n" + " }\n" + " }\n" + " return QImage();\n" + "}\n\n"; + + out << "class MimeSourceFactory_" << cProject << " : public Q3MimeSourceFactory\n"; + out << "{\n"; + out << "public:\n"; + out << " MimeSourceFactory_" << cProject << "() {}\n"; + out << " ~MimeSourceFactory_" << cProject << "() {}\n"; + out << " const QMimeSource* data( const QString& abs_name ) const {\n"; + out << "\tconst QMimeSource* d = Q3MimeSourceFactory::data( abs_name );\n"; + out << "\tif ( d || abs_name.isNull() ) return d;\n"; + out << "\tQImage img = uic_findImage( abs_name );\n"; + out << "\tif ( !img.isNull() )\n"; + out << "\t ((Q3MimeSourceFactory*)this)->setImage( abs_name, img );\n"; + out << "\treturn Q3MimeSourceFactory::data( abs_name );\n"; + out << " };\n"; + out << "};\n\n"; + + out << "static Q3MimeSourceFactory* factory = 0;\n"; + out << "\n"; + + out << "void qInitImages_" << cProject << "()\n"; + out << "{\n"; + out << " if ( !factory ) {\n"; + out << "\tfactory = new MimeSourceFactory_" << cProject << ";\n"; + out << "\tQ3MimeSourceFactory::defaultFactory()->addFactory( factory );\n"; + out << " }\n"; + out << "}\n\n"; + + out << "void qCleanupImages_" << cProject << "()\n"; + out << "{\n"; + out << " if ( factory ) {\n"; + out << "\tQ3MimeSourceFactory::defaultFactory()->removeFactory( factory );\n"; + out << "\tdelete factory;\n"; + out << "\tfactory = 0;\n"; + out << " }\n"; + out << "}\n\n"; + + out << "class StaticInitImages_" << cProject << "\n"; + out << "{\n"; + out << "public:\n"; + out << " StaticInitImages_" << cProject << "() { qInitImages_" << cProject << "(); }\n"; + out << "#if defined(Q_OS_SCO) || defined(Q_OS_UNIXWARE)\n"; + out << " ~StaticInitImages_" << cProject << "() { }\n"; + out << "#else\n"; + out << " ~StaticInitImages_" << cProject << "() { qCleanupImages_" << cProject << "(); }\n"; + out << "#endif\n"; + out << "};\n\n"; + + out << "static StaticInitImages_" << cProject << " staticImages;\n"; + } +} + +QT_END_NAMESPACE diff --git a/src/tools/uic3/form.cpp b/src/tools/uic3/form.cpp new file mode 100644 index 0000000..d9e968b --- /dev/null +++ b/src/tools/uic3/form.cpp @@ -0,0 +1,921 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "ui3reader.h" +#include "parser.h" +#include "domtool.h" +#include "globaldefs.h" + +// uic4 +#include "uic.h" +#include "ui4.h" +#include "driver.h" +#include "option.h" + +#include <QStringList> +#include <QFile> +#include <QFileInfo> +#include <QDir> +#include <QRegExp> +#include <QtDebug> + +QT_BEGIN_NAMESPACE + +QByteArray combinePath(const char *infile, const char *outfile) +{ + QFileInfo inFileInfo(QDir::current(), QFile::decodeName(infile)); + QFileInfo outFileInfo(QDir::current(), QFile::decodeName(outfile)); + int numCommonComponents = 0; + + QStringList inSplitted = inFileInfo.dir().canonicalPath().split(QLatin1Char('/')); + QStringList outSplitted = outFileInfo.dir().canonicalPath().split(QLatin1Char('/')); + + while (!inSplitted.isEmpty() && !outSplitted.isEmpty() && + inSplitted.first() == outSplitted.first()) { + inSplitted.erase(inSplitted.begin()); + outSplitted.erase(outSplitted.begin()); + numCommonComponents++; + } + + if (numCommonComponents < 2) { + /* + The paths don't have the same drive, or they don't have the + same root directory. Use an absolute path. + */ + return QFile::encodeName(inFileInfo.absoluteFilePath()); + } else { + /* + The paths have something in common. Use a path relative to + the output file. + */ + while (!outSplitted.isEmpty()) { + outSplitted.erase(outSplitted.begin()); + inSplitted.prepend(QLatin1String("..")); + } + inSplitted.append(inFileInfo.fileName()); + return QFile::encodeName(inSplitted.join(QLatin1String("/"))); + } +} + +/*! + Creates a declaration (header file) for the form given in \a e + + \sa createFormImpl() +*/ +void Ui3Reader::createFormDecl(const QDomElement &e, bool implicitIncludes) +{ + QDomElement body = e; + + QDomElement n; + QDomNodeList nl; + int i; + QString objClass = getClassName(e); + if (objClass.isEmpty()) + return; + QString objName = getObjectName(e); + + QStringList typeDefs; + + QMap<QString, CustomInclude> customWidgetIncludes; + + /* + We are generating a few QImage members that are not strictly + necessary in some cases. Ideally, we would use requiredImage, + which is computed elsewhere, to keep the generated .h and .cpp + files synchronized. + */ + + // at first the images + QMap<QString, int> customWidgets; + QStringList forwardDecl; + QStringList forwardDecl2; + for (n = e; !n.isNull(); n = n.nextSibling().toElement()) { + if (n.tagName().toLower() == QLatin1String("customwidgets")) { + QDomElement n2 = n.firstChild().toElement(); + while (!n2.isNull()) { + if (n2.tagName().toLower() == QLatin1String("customwidget")) { + QDomElement n3 = n2.firstChild().toElement(); + QString cl; + while (!n3.isNull()) { + QString tagName = n3.tagName().toLower(); + if (tagName == QLatin1String("class")) { + cl = n3.firstChild().toText().data(); + if (!nofwd) + forwardDecl << cl; + customWidgets.insert(cl, 0); + } else if (tagName == QLatin1String("header")) { + CustomInclude ci; + ci.header = n3.firstChild().toText().data(); + ci.location = n3.attribute(QLatin1String("location"), QLatin1String("global")); + if (!ci.header.isEmpty()) + forwardDecl.removeAll(cl); + customWidgetIncludes.insert(cl, ci); + } + n3 = n3.nextSibling().toElement(); + } + } + n2 = n2.nextSibling().toElement(); + } + } + } + + // register the object and unify its name + objName = registerObject(objName); + QString protector = objName.toUpper() + QLatin1String("_H"); + protector.replace(QLatin1String("::"), QLatin1String("_")); + out << "#ifndef " << protector << endl; + out << "#define " << protector << endl; + out << endl; + + out << "#include <qvariant.h>" << endl; // for broken HP-UX compilers + + QStringList globalIncludes, localIncludes; + + { + QMap<QString, CustomInclude>::Iterator it = customWidgetIncludes.find(objClass); + if (it != customWidgetIncludes.end()) { + if ((*it).location == QLatin1String("global")) + globalIncludes += (*it).header; + else + localIncludes += (*it).header; + } + } + + QStringList::ConstIterator it; + + globalIncludes = unique(globalIncludes); + for (it = globalIncludes.constBegin(); it != globalIncludes.constEnd(); ++it) { + if (!(*it).isEmpty()) { + QString header = fixHeaderName(*it); + out << "#include <" << header << ">" << endl; + } + } + localIncludes = unique(localIncludes); + for (it = localIncludes.constBegin(); it != localIncludes.constEnd(); ++it) { + if (!(*it).isEmpty()) { + QString header = fixHeaderName(*it); + out << "#include \"" << header << "\"" << endl; + } + } + out << endl; + + bool dbForm = false; + registerDatabases(e); + dbConnections = unique(dbConnections); + if (dbForms[QLatin1String("(default)")].count()) + dbForm = true; + bool subDbForms = false; + for (it = dbConnections.constBegin(); it != dbConnections.constEnd(); ++it) { + if (!(*it).isEmpty() && (*it) != QLatin1String("(default)")) { + if (dbForms[(*it)].count()) { + subDbForms = true; + break; + } + } + } + + // some typedefs, maybe + typeDefs = unique(typeDefs); + for (it = typeDefs.constBegin(); it != typeDefs.constEnd(); ++it) { + if (!(*it).isEmpty()) + out << "typedef " << *it << ";" << endl; + } + + nl = e.parentNode().toElement().elementsByTagName(QLatin1String("forward")); + for (i = 0; i < (int) nl.length(); i++) + forwardDecl2 << fixDeclaration(nl.item(i).toElement().firstChild().toText().data()); + + forwardDecl = unique(forwardDecl); + for (it = forwardDecl.constBegin(); it != forwardDecl.constEnd(); ++it) { + if (!(*it).isEmpty() && (*it) != objClass) { + QString forwardName = *it; + QStringList forwardNamespaces = forwardName.split(QLatin1String("::")); + forwardName = forwardNamespaces.last(); + forwardNamespaces.removeAt(forwardNamespaces.size()-1); + + QStringList::ConstIterator ns = forwardNamespaces.constBegin(); + while (ns != forwardNamespaces.constEnd()) { + out << "namespace " << *ns << " {" << endl; + ++ns; + } + out << "class " << forwardName << ";" << endl; + for (int i = 0; i < (int) forwardNamespaces.count(); i++) + out << "}" << endl; + } + } + + for (it = forwardDecl2.constBegin(); it != forwardDecl2.constEnd(); ++it) { + QString fd = *it; + fd = fd.trimmed(); + if (!fd.endsWith(QLatin1String(";"))) + fd += QLatin1String(";"); + out << fd << endl; + } + + out << endl; + + Driver d; + d.option().headerProtection = false; + d.option().copyrightHeader = false; + d.option().extractImages = m_extractImages; + d.option().qrcOutputFile = m_qrcOutputFile; + d.option().implicitIncludes = implicitIncludes; + if (trmacro.size()) + d.option().translateFunction = trmacro; + DomUI *ui = generateUi4(e, implicitIncludes); + d.uic(fileName, ui, &out); + delete ui; + + createWrapperDeclContents(e); + + out << "#endif // " << protector << endl; +} + +void Ui3Reader::createWrapperDecl(const QDomElement &e, const QString &convertedUiFile) +{ + QString objName = getObjectName(e); + + objName = registerObject(objName); + QString protector = objName.toUpper() + QLatin1String("_H"); + protector.replace(QLatin1String("::"), QLatin1String("_")); + out << "#ifndef " << protector << endl; + out << "#define " << protector << endl; + out << endl; + out << "#include \"" << convertedUiFile << "\"" << endl; + + createWrapperDeclContents(e); + out << endl; + out << "#endif // " << protector << endl; +} + +void Ui3Reader::createWrapperDeclContents(const QDomElement &e) +{ + QString objClass = getClassName(e); + if (objClass.isEmpty()) + return; + + QDomNodeList nl; + QString exportMacro; + int i; + QDomElement n; + QStringList::ConstIterator it; + nl = e.parentNode().toElement().elementsByTagName(QLatin1String("exportmacro")); + if (nl.length() == 1) + exportMacro = nl.item(0).firstChild().toText().data(); + + QStringList::ConstIterator ns = namespaces.constBegin(); + while (ns != namespaces.constEnd()) { + out << "namespace " << *ns << " {" << endl; + ++ns; + } + + out << "class "; + if (!exportMacro.isEmpty()) + out << exportMacro << " "; + out << bareNameOfClass << " : public " << objClass << ", public Ui::" << bareNameOfClass << endl << "{" << endl; + + /* qmake ignore Q_OBJECT */ + out << " Q_OBJECT" << endl; + out << endl; + out << "public:" << endl; + + // constructor + if (objClass == QLatin1String("QDialog") || objClass == QLatin1String("QWizard")) { + out << " " << bareNameOfClass << "(QWidget* parent = 0, const char* name = 0, bool modal = false, Qt::WindowFlags fl = 0);" << endl; + } else if (objClass == QLatin1String("QWidget")) { + out << " " << bareNameOfClass << "(QWidget* parent = 0, const char* name = 0, Qt::WindowFlags fl = 0);" << endl; + } else if (objClass == QLatin1String("QMainWindow") || objClass == QLatin1String("Q3MainWindow")) { + out << " " << bareNameOfClass << "(QWidget* parent = 0, const char* name = 0, Qt::WindowFlags fl = Qt::WType_TopLevel);" << endl; + isMainWindow = true; + } else { + out << " " << bareNameOfClass << "(QWidget* parent = 0, const char* name = 0);" << endl; + } + + // destructor + out << " ~" << bareNameOfClass << "();" << endl; + out << endl; + + // database connections + dbConnections = unique(dbConnections); + bool hadOutput = false; + for (it = dbConnections.constBegin(); it != dbConnections.constEnd(); ++it) { + if (!(*it).isEmpty()) { + // only need pointers to non-default connections + if ((*it) != QLatin1String("(default)") && !(*it).isEmpty()) { + out << indent << "QSqlDatabase* " << *it << "Connection;" << endl; + hadOutput = true; + } + } + } + if (hadOutput) + out << endl; + + QStringList publicSlots, protectedSlots, privateSlots; + QStringList publicSlotTypes, protectedSlotTypes, privateSlotTypes; + QStringList publicSlotSpecifier, protectedSlotSpecifier, privateSlotSpecifier; + + nl = e.parentNode().toElement().elementsByTagName(QLatin1String("slot")); + for (i = 0; i < (int) nl.length(); i++) { + n = nl.item(i).toElement(); + if (n.parentNode().toElement().tagName() != QLatin1String("slots") + && n.parentNode().toElement().tagName() != QLatin1String("connections")) + continue; + if (n.attribute(QLatin1String("language"), QLatin1String("C++")) != QLatin1String("C++")) + continue; + QString returnType = n.attribute(QLatin1String("returnType"), QLatin1String("void")); + QString functionName = n.firstChild().toText().data().trimmed(); + if (functionName.endsWith(QLatin1String(";"))) + functionName = functionName.left(functionName.length() - 1); + QString specifier = n.attribute(QLatin1String("specifier")); + QString access = n.attribute(QLatin1String("access")); + if (access == QLatin1String(QLatin1String("protected"))) { + protectedSlots += functionName; + protectedSlotTypes += returnType; + protectedSlotSpecifier += specifier; + } else if (access == QLatin1String("private")) { + privateSlots += functionName; + privateSlotTypes += returnType; + privateSlotSpecifier += specifier; + } else { + publicSlots += functionName; + publicSlotTypes += returnType; + publicSlotSpecifier += specifier; + } + } + + QStringList publicFuncts, protectedFuncts, privateFuncts; + QStringList publicFunctRetTyp, protectedFunctRetTyp, privateFunctRetTyp; + QStringList publicFunctSpec, protectedFunctSpec, privateFunctSpec; + + nl = e.parentNode().toElement().elementsByTagName(QLatin1String("function")); + for (i = 0; i < (int) nl.length(); i++) { + n = nl.item(i).toElement(); + if (n.parentNode().toElement().tagName() != QLatin1String("functions")) + continue; + if (n.attribute(QLatin1String("language"), QLatin1String("C++")) != QLatin1String("C++")) + continue; + QString returnType = n.attribute(QLatin1String("returnType"), QLatin1String("void")); + QString functionName = n.firstChild().toText().data().trimmed(); + if (functionName.endsWith(QLatin1String(";"))) + functionName = functionName.left(functionName.length() - 1); + QString specifier = n.attribute(QLatin1String("specifier")); + QString access = n.attribute(QLatin1String("access")); + if (access == QLatin1String("protected")) { + protectedFuncts += functionName; + protectedFunctRetTyp += returnType; + protectedFunctSpec += specifier; + } else if (access == QLatin1String("private")) { + privateFuncts += functionName; + privateFunctRetTyp += returnType; + privateFunctSpec += specifier; + } else { + publicFuncts += functionName; + publicFunctRetTyp += returnType; + publicFunctSpec += specifier; + } + } + + QStringList publicVars, protectedVars, privateVars; + nl = e.parentNode().toElement().elementsByTagName(QLatin1String("variable")); + for (i = 0; i < (int)nl.length(); i++) { + n = nl.item(i).toElement(); + // Because of compatibility the next lines have to be commented out. + // Someday it should be uncommented. + //if (n.parentNode().toElement().tagName() != QLatin1String("variables")) + // continue; + QString access = n.attribute(QLatin1String("access"), QLatin1String("protected")); + QString var = fixDeclaration(n.firstChild().toText().data().trimmed()); + if (!var.endsWith(QLatin1String(";"))) + var += QLatin1String(";"); + if (access == QLatin1String("public")) + publicVars += var; + else if (access == QLatin1String("private")) + privateVars += var; + else + protectedVars += var; + } + + if (!publicVars.isEmpty()) { + for (it = publicVars.constBegin(); it != publicVars.constEnd(); ++it) + out << indent << *it << endl; + out << endl; + } + if (!publicFuncts.isEmpty()) + writeFunctionsDecl(publicFuncts, publicFunctRetTyp, publicFunctSpec); + + if (!publicSlots.isEmpty()) { + out << "public slots:" << endl; + if (!publicSlots.isEmpty()) + writeFunctionsDecl(publicSlots, publicSlotTypes, publicSlotSpecifier); + } + + // find signals + QStringList extraSignals; + nl = e.parentNode().toElement().elementsByTagName(QLatin1String("signal")); + for (i = 0; i < (int) nl.length(); i++) { + n = nl.item(i).toElement(); + if (n.parentNode().toElement().tagName() != QLatin1String("signals") + && n.parentNode().toElement().tagName() != QLatin1String("connections")) + continue; + if (n.attribute(QLatin1String("language"), QLatin1String("C++")) != QLatin1String("C++")) + continue; + QString sigName = n.firstChild().toText().data().trimmed(); + if (sigName.endsWith(QLatin1String(";"))) + sigName = sigName.left(sigName.length() - 1); + extraSignals += fixDeclaration(sigName); + } + + // create signals + if (!extraSignals.isEmpty()) { + out << "signals:" << endl; + for (it = extraSignals.constBegin(); it != extraSignals.constEnd(); ++it) + out << " void " << (*it) << ";" << endl; + out << endl; + } + + if (!protectedVars.isEmpty()) { + out << "protected:" << endl; + for (it = protectedVars.constBegin(); it != protectedVars.constEnd(); ++it) + out << indent << *it << endl; + out << endl; + } + + if (!protectedFuncts.isEmpty()) { + if (protectedVars.isEmpty()) + out << "protected:" << endl; + + writeFunctionsDecl(protectedFuncts, protectedFunctRetTyp, protectedFunctSpec); + } + + out << "protected slots:" << endl; + out << " virtual void languageChange();" << endl; + + if (!protectedSlots.isEmpty()) { + out << endl; + writeFunctionsDecl(protectedSlots, protectedSlotTypes, protectedSlotSpecifier); + } + out << endl; + + // create all private stuff + if (!privateFuncts.isEmpty() || !privateVars.isEmpty()) { + out << "private:" << endl; + if (!privateVars.isEmpty()) { + for (it = privateVars.constBegin(); it != privateVars.constEnd(); ++it) + out << indent << *it << endl; + out << endl; + } + if (!privateFuncts.isEmpty()) + writeFunctionsDecl(privateFuncts, privateFunctRetTyp, privateFunctSpec); + } + + if (!privateSlots.isEmpty()) { + out << "private slots:" << endl; + writeFunctionsDecl(privateSlots, privateSlotTypes, privateSlotSpecifier); + } + + out << "};" << endl; + for (i = 0; i < (int) namespaces.count(); i++) + out << "}" << endl; + + out << endl; +} + +void Ui3Reader::writeFunctionsDecl(const QStringList &fuLst, const QStringList &typLst, const QStringList &specLst) +{ + QStringList::ConstIterator it, it2, it3; + for (it = fuLst.begin(), it2 = typLst.begin(), it3 = specLst.begin(); + it != fuLst.end(); ++it, ++it2, ++it3) { + QString signature = *it; + QString specifier; + QString pure; + QString type = *it2; + if (type.isEmpty()) + type = QLatin1String("void"); + if (*it3 == QLatin1String("static")) { + specifier = QLatin1String("static "); + } else { + if (*it3 != QLatin1String("non virtual") && *it3 != QLatin1String("nonVirtual")) + specifier = QLatin1String("virtual "); + if (*it3 == QLatin1String("pure virtual") || *it3 == QLatin1String("pureVirtual")) + pure = QLatin1String(" = 0"); + } + type.replace(QLatin1String(">>"), QLatin1String("> >")); + if (!signature.contains(QLatin1String("operator"))) + signature.replace(QLatin1String(">>"), QLatin1String("> >")); + + signature = fixDeclaration(signature); + type = fixType(type); + out << " " << specifier << type << " " << signature << pure << ";" << endl; + } + out << endl; +} + +/*! + Creates an implementation (cpp-file) for the form given in \a e. + + \sa createFormDecl(), createObjectImpl() + */ +void Ui3Reader::createFormImpl(const QDomElement &e) +{ + QDomElement n; + QDomNodeList nl; + int i; + QString objClass = getClassName(e); + if (objClass.isEmpty()) + return; + QString objName = getObjectName(e); + + // generate local and local includes required + QStringList globalIncludes, localIncludes; + QStringList::Iterator it; + + QMap<QString, CustomInclude> customWidgetIncludes; + + // find additional slots and functions + QStringList extraFuncts; + QStringList extraFunctTyp; + QStringList extraFunctSpecifier; + + nl = e.parentNode().toElement().elementsByTagName(QLatin1String("slot")); + for (i = 0; i < (int) nl.length(); i++) { + n = nl.item(i).toElement(); + if (n.parentNode().toElement().tagName() != QLatin1String("slots") + && n.parentNode().toElement().tagName() != QLatin1String("connections")) + continue; + if (n.attribute(QLatin1String("language"), QLatin1String("C++")) != QLatin1String("C++")) + continue; + QString functionName = n.firstChild().toText().data().trimmed(); + if (functionName.endsWith(QLatin1String(";"))) + functionName = functionName.left(functionName.length() - 1); + extraFuncts += functionName; + extraFunctTyp += n.attribute(QLatin1String("returnType"), QLatin1String("void")); + extraFunctSpecifier += n.attribute(QLatin1String("specifier"), QLatin1String("virtual")); + } + + nl = e.parentNode().toElement().elementsByTagName(QLatin1String("function")); + for (i = 0; i < (int) nl.length(); i++) { + n = nl.item(i).toElement(); + if (n.parentNode().toElement().tagName() != QLatin1String("functions")) + continue; + if (n.attribute(QLatin1String("language"), QLatin1String("C++")) != QLatin1String("C++")) + continue; + QString functionName = n.firstChild().toText().data().trimmed(); + if (functionName.endsWith(QLatin1String(";"))) + functionName = functionName.left(functionName.length() - 1); + extraFuncts += functionName; + extraFunctTyp += n.attribute(QLatin1String("returnType"), QLatin1String("void")); + extraFunctSpecifier += n.attribute(QLatin1String("specifier"), QLatin1String("virtual")); + } + + // additional includes (local or global) and forward declaractions + nl = e.parentNode().toElement().elementsByTagName(QLatin1String("include")); + for (i = 0; i < (int) nl.length(); i++) { + QDomElement n2 = nl.item(i).toElement(); + QString s = n2.firstChild().toText().data(); + if (n2.attribute(QLatin1String("location")) != QLatin1String("local")) { + if (s.right(5) == QLatin1String(".ui.h") && !QFile::exists(s)) + continue; + if (n2.attribute(QLatin1String("impldecl"), QLatin1String("in implementation")) != QLatin1String("in implementation")) + continue; + globalIncludes += s; + } + } + + registerDatabases(e); + dbConnections = unique(dbConnections); + bool dbForm = false; + if (dbForms[QLatin1String("(default)")].count()) + dbForm = true; + bool subDbForms = false; + for (it = dbConnections.begin(); it != dbConnections.end(); ++it) { + if (!(*it).isEmpty() && (*it) != QLatin1String("(default)")) { + if (dbForms[(*it)].count()) { + subDbForms = true; + break; + } + } + } + + // do the local includes afterwards, since global includes have priority on clashes + for (i = 0; i < (int) nl.length(); i++) { + QDomElement n2 = nl.item(i).toElement(); + QString s = n2.firstChild().toText().data(); + if (n2.attribute(QLatin1String("location")) == QLatin1String("local") && !globalIncludes.contains(s)) { + if (s.right(5) == QLatin1String(".ui.h") && !QFile::exists(s)) + continue; + if (n2.attribute(QLatin1String("impldecl"), QLatin1String("in implementation")) != QLatin1String("in implementation")) + continue; + localIncludes += s; + } + } + + // additional custom widget headers + nl = e.parentNode().toElement().elementsByTagName(QLatin1String("header")); + for (i = 0; i < (int) nl.length(); i++) { + QDomElement n2 = nl.item(i).toElement(); + QString s = n2.firstChild().toText().data(); + if (n2.attribute(QLatin1String("location")) != QLatin1String("local")) + globalIncludes += s; + else + localIncludes += s; + } + + out << "#include <qvariant.h>" << endl; // first for gcc 2.7.2 + + globalIncludes = unique(globalIncludes); + for (it = globalIncludes.begin(); it != globalIncludes.end(); ++it) { + if (!(*it).isEmpty()) + out << "#include <" << fixHeaderName(*it) << ">" << endl; + } + + if (externPixmaps) { + out << "#include <qimage.h>" << endl; + out << "#include <qpixmap.h>" << endl << endl; + } + + /* + Put local includes after all global includes + */ + localIncludes = unique(localIncludes); + for (it = localIncludes.begin(); it != localIncludes.end(); ++it) { + if (!(*it).isEmpty() && *it != QFileInfo(fileName + QLatin1String(".h")).fileName()) + out << "#include \"" << fixHeaderName(*it) << "\"" << endl; + } + + QString uiDotH = fileName + QLatin1String(".h"); + if (QFile::exists(uiDotH)) { + if (!outputFileName.isEmpty()) + uiDotH = QString::fromUtf8(combinePath(uiDotH.ascii(), outputFileName.ascii())); + out << "#include \"" << uiDotH << "\"" << endl; + writeFunctImpl = false; + } + + // register the object and unify its name + objName = registerObject(objName); + + if (externPixmaps) { + pixmapLoaderFunction = QLatin1String("QPixmap::fromMimeSource"); + } + + // constructor + if (objClass == QLatin1String("QDialog") || objClass == QLatin1String("QWizard")) { + out << "/*" << endl; + out << " * Constructs a " << nameOfClass << " as a child of 'parent', with the" << endl; + out << " * name 'name' and widget flags set to 'f'." << endl; + out << " *" << endl; + out << " * The " << objClass.mid(1).toLower() << " will by default be modeless, unless you set 'modal' to" << endl; + out << " * true to construct a modal " << objClass.mid(1).toLower() << "." << endl; + out << " */" << endl; + out << nameOfClass << "::" << bareNameOfClass << "(QWidget* parent, const char* name, bool modal, Qt::WindowFlags fl)" << endl; + out << " : " << objClass << "(parent, name, modal, fl)"; + } else if (objClass == QLatin1String("QWidget")) { + out << "/*" << endl; + out << " * Constructs a " << nameOfClass << " as a child of 'parent', with the" << endl; + out << " * name 'name' and widget flags set to 'f'." << endl; + out << " */" << endl; + out << nameOfClass << "::" << bareNameOfClass << "(QWidget* parent, const char* name, Qt::WindowFlags fl)" << endl; + out << " : " << objClass << "(parent, name, fl)"; + } else if (objClass == QLatin1String("QMainWindow") || objClass == QLatin1String("Q3MainWindow")) { + out << "/*" << endl; + out << " * Constructs a " << nameOfClass << " as a child of 'parent', with the" << endl; + out << " * name 'name' and widget flags set to 'f'." << endl; + out << " *" << endl; + out << " */" << endl; + out << nameOfClass << "::" << bareNameOfClass << "(QWidget* parent, const char* name, Qt::WindowFlags fl)" << endl; + out << " : " << objClass << "(parent, name, fl)"; + isMainWindow = true; + } else { + out << "/*" << endl; + out << " * Constructs a " << nameOfClass << " which is a child of 'parent', with the" << endl; + out << " * name 'name'.' " << endl; + out << " */" << endl; + out << nameOfClass << "::" << bareNameOfClass << "(QWidget* parent, const char* name)" << endl; + out << " : " << objClass << "(parent, name)"; + } + + out << endl; + + out << "{" << endl; + +// +// setup the gui +// + out << indent << "setupUi(this);" << endl << endl; + + + if (isMainWindow) + out << indent << "(void)statusBar();" << endl; + + // database support + dbConnections = unique(dbConnections); + if (dbConnections.count()) + out << endl; + for (it = dbConnections.begin(); it != dbConnections.end(); ++it) { + if (!(*it).isEmpty() && (*it) != QLatin1String("(default)")) { + out << indent << (*it) << "Connection = QSqlDatabase::database(\"" <<(*it) << "\");" << endl; + } + } + + nl = e.parentNode().toElement().elementsByTagName(QLatin1String("widget")); + for (i = 1; i < (int) nl.length(); i++) { // start at 1, 0 is the toplevel widget + n = nl.item(i).toElement(); + QString s = getClassName(n); + if ((dbForm || subDbForms) && (s == QLatin1String("QDataBrowser") || s == QLatin1String("QDataView"))) { + QString objName = getObjectName(n); + QString tab = getDatabaseInfo(n, QLatin1String("table")); + QString con = getDatabaseInfo(n, QLatin1String("connection")); + out << indent << "QSqlForm* " << objName << "Form = new QSqlForm(this);" << endl; + out << indent << objName << "Form->setObjectName(\"" << objName << "Form\");" << endl; + QDomElement n2; + for (n2 = n.firstChild().toElement(); !n2.isNull(); n2 = n2.nextSibling().toElement()) + createFormImpl(n2, objName, con, tab); + out << indent << objName << "->setForm(" << objName << "Form);" << endl; + } + } + + if (extraFuncts.contains(QLatin1String("init()"))) + out << indent << "init();" << endl; + + // end of constructor + out << "}" << endl; + out << endl; + + // destructor + out << "/*" << endl; + out << " * Destroys the object and frees any allocated resources" << endl; + out << " */" << endl; + out << nameOfClass << "::~" << bareNameOfClass << "()" << endl; + out << "{" << endl; + if (extraFuncts.contains(QLatin1String("destroy()"))) + out << indent << "destroy();" << endl; + out << indent << "// no need to delete child widgets, Qt does it all for us" << endl; + out << "}" << endl; + out << endl; + + // handle application events if required + bool needFontEventHandler = false; + bool needSqlTableEventHandler = false; + bool needSqlDataBrowserEventHandler = false; + nl = e.elementsByTagName(QLatin1String("widget")); + for (i = 0; i < (int) nl.length(); i++) { + if (!DomTool::propertiesOfType(nl.item(i).toElement() , QLatin1String("font")).isEmpty()) + needFontEventHandler = true; + QString s = getClassName(nl.item(i).toElement()); + if (s == QLatin1String("QDataTable") || s == QLatin1String("QDataBrowser")) { + if (!isFrameworkCodeGenerated(nl.item(i).toElement())) + continue; + if (s == QLatin1String("QDataTable")) + needSqlTableEventHandler = true; + if (s == QLatin1String("QDataBrowser")) + needSqlDataBrowserEventHandler = true; + } + if (needFontEventHandler && needSqlTableEventHandler && needSqlDataBrowserEventHandler) + break; + } + + out << "/*" << endl; + out << " * Sets the strings of the subwidgets using the current" << endl; + out << " * language." << endl; + out << " */" << endl; + out << "void " << nameOfClass << "::languageChange()" << endl; + out << "{" << endl; + out << " retranslateUi(this);" << endl; + out << "}" << endl; + out << endl; + + // create stubs for additional slots if necessary + if (!extraFuncts.isEmpty() && writeFunctImpl) { + it = extraFuncts.begin(); + QStringList::Iterator it2 = extraFunctTyp.begin(); + QStringList::Iterator it3 = extraFunctSpecifier.begin(); + while (it != extraFuncts.end()) { + QString type = fixDeclaration(*it2); + if (type.isEmpty()) + type = QLatin1String("void"); + type = type.simplified(); + QString fname = fixDeclaration(Parser::cleanArgs(*it)); + if (!(*it3).startsWith(QLatin1String("pure"))) { // "pure virtual" or "pureVirtual" + out << type << " " << nameOfClass << "::" << fname << endl; + out << "{" << endl; + if (*it != QLatin1String("init()") && *it != QLatin1String("destroy()")) { + QRegExp numeric(QLatin1String("^(?:signed|unsigned|u?char|u?short|u?int" + "|u?long|Q_U?INT(?:8|16|32)|Q_U?LONG|float" + "|double)$")); + QString retVal; + + /* + We return some kind of dummy value to shut the + compiler up. + + 1. If the type is 'void', we return nothing. + + 2. If the type is 'bool', we return 'false'. + + 3. If the type is 'unsigned long' or + 'quint16' or 'double' or similar, we + return '0'. + + 4. If the type is 'Foo *', we return '0'. + + 5. If the type is 'Foo &', we create a static + variable of type 'Foo' and return it. + + 6. If the type is 'Foo', we assume there's a + default constructor and use it. + */ + if (type != QLatin1String("void")) { + QStringList toks = type.split(QLatin1String(" ")); + bool isBasicNumericType = + (toks.filter(numeric).count() == toks.count()); + + if (type == QLatin1String("bool")) { + retVal = QLatin1String("false"); + } else if (isBasicNumericType || type.endsWith(QLatin1String("*"))) { + retVal = QLatin1String("0"); + } else if (type.endsWith(QLatin1String("&"))) { + do { + type.chop(1); + } while (type.endsWith(QLatin1String(" "))); + retVal = QLatin1String("uic_temp_var"); + out << indent << "static " << type << " " << retVal << ";" << endl; + } else { + retVal = type + QLatin1String("()"); + } + } + + out << indent << "qWarning(\"" << nameOfClass << "::" << fname << ": Not implemented yet\");" << endl; + if (!retVal.isEmpty()) + out << indent << "return " << retVal << ";" << endl; + } + out << "}" << endl; + out << endl; + } + ++it; + ++it2; + ++it3; + } + } +} + + +/*! Creates form support implementation code for the widgets given + in \a e. + + Traverses recursively over all children. + */ + +void Ui3Reader::createFormImpl(const QDomElement& e, const QString& form, const QString& connection, const QString& table) +{ + if (e.tagName() == QLatin1String("widget") + && e.attribute(QLatin1String("class")) != QLatin1String("QDataTable")) { + QString field = getDatabaseInfo(e, QLatin1String("field")); + if (!field.isEmpty()) { + if (isWidgetInTable(e, connection, table)) + out << indent << form << "Form->insert(" << getObjectName(e) << ", " << fixString(field) << ");" << endl; + } + } + QDomElement n; + for (n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement()) { + createFormImpl(n, form, connection, table); + } +} + +QT_END_NAMESPACE diff --git a/src/tools/uic3/main.cpp b/src/tools/uic3/main.cpp new file mode 100644 index 0000000..d581016 --- /dev/null +++ b/src/tools/uic3/main.cpp @@ -0,0 +1,414 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "ui3reader.h" +#include "domtool.h" +#include "globaldefs.h" + +#include <QApplication> +#include <QFile> +#include <QFileInfo> +#include <QStringList> +#include <QDateTime> +#include <QSettings> +#include <stdio.h> +#include <stdlib.h> + +#if defined Q_WS_WIN +#include <qt_windows.h> +#endif + +QT_BEGIN_NAMESPACE + +int runUic3(int argc, char * argv[]) +{ + bool impl = false; + bool wrap = false; + bool subcl = false; + bool extract = false; + bool imagecollection = false; + bool imagecollection_tmpfile = false; + bool convert = false; + QStringList images; + const char *error = 0; + const char* fileName = 0; + const char* className = 0; + const char* headerFile = 0; + const char* convertedUiFile = 0; + QByteArray outputFile; + QString qrcOutputFile; + QByteArray image_tmpfile; + const char* projectName = 0; + const char* trmacro = 0; + bool nofwd = false; + bool fix = false; + bool deps = false; + bool implicitIncludes = true; + QByteArray pchFile; + + + QApplication app(argc, argv, false); + + for (int n = 1; n < argc && error == 0; n++) { + QByteArray arg = argv[n]; + if (arg[0] == '-') { // option + QByteArray opt = arg.data() + 1; + if (opt[0] == 'o') { // output redirection + if (opt[1] == '\0') { + if (!(n < argc-1)) { + error = "Missing output-file name"; + break; + } + outputFile = argv[++n]; + } else + outputFile = opt.data() + 1; + } else if (opt[0] == 'i' || opt == "impl") { + impl = true; + if (opt == "impl" || opt[1] == '\0') { + if (!(n < argc-1)) { + error = "Missing name of header file"; + break; + } + headerFile = argv[++n]; + } else + headerFile = opt.data() + 1; + } else if (opt[0] == 'w' || opt == "wrap") { + wrap = true; + if (opt == "wrap" || opt[1] == '\0') { + if (!(n < argc-1)) { + error = "Missing name of converted ui file"; + break; + } + convertedUiFile = argv[++n]; + } else + convertedUiFile = opt.data() + 1; + } else if (opt == "extract") { // output redirection + extract = true; + if (!(n < argc-1)) { + error = "Missing output qrc-file name"; + break; + } + qrcOutputFile = QFile::decodeName(argv[++n]); + } else if ( opt[0] == 'e' || opt == "embed" ) { + imagecollection = true; + if ( opt == "embed" || opt[1] == '\0' ) { + if ( !(n < argc-1) ) { + error = "Missing name of project"; + break; + } + projectName = argv[++n]; + } else { + projectName = opt.data() + 1; + } + if ( argc > n+1 && qstrcmp( argv[n+1], "-f" ) == 0 ) { + imagecollection_tmpfile = true; + image_tmpfile = argv[n+2]; + n += 2; + } + } else if (opt == "d") { + deps = true; + } else if (opt == "no-implicit-includes") { + implicitIncludes = false; + } else if (opt == "nofwd") { + nofwd = true; + } else if (opt == "nounload") { + // skip + } else if (opt == "convert") { + convert = true; + } else if (opt == "subdecl") { + subcl = true; + if (!(n < argc-2)) { + error = "Missing arguments"; + break; + } + className = argv[++n]; + headerFile = argv[++n]; + } else if (opt == "subimpl") { + subcl = true; + impl = true; + if (!(n < argc-2)) { + error = "Missing arguments"; + break; + } + className = argv[++n]; + headerFile = argv[++n]; + } else if (opt == "tr") { + if (opt == "tr" || opt[1] == '\0') { + if (!(n < argc-1)) { + error = "Missing tr macro."; + break; + } + trmacro = argv[++n]; + } else { + trmacro = opt.data() + 1; + } + } else if (opt == "L") { + if (!(n < argc-1)) { + error = "Missing plugin path."; + break; + } + ++n; // ignore the next argument + } else if (opt == "version") { + fprintf(stderr, + "Qt User Interface Compiler version %s\n", + QT_VERSION_STR); + return 1; + } else if (opt == "help") { + break; + } else if (opt == "fix") { + fix = true; + } else if (opt == "pch") { + if (!(n < argc-1)) { + error = "Missing name of PCH file"; + break; + } + pchFile = argv[++n]; + } else { + error = "Unrecognized option"; + } + } else { + if (imagecollection && !imagecollection_tmpfile) + images << QLatin1String(argv[n]); + else if (fileName) // can handle only one file + error = "Too many input files specified"; + else + fileName = argv[n]; + } + } + + if (argc < 2 || error || (!fileName && !imagecollection)) { + fprintf(stderr, + "Qt User Interface Compiler version %s\n", + QT_VERSION_STR); + if (error) + fprintf(stderr, "uic: %s\n", error); + + fprintf(stderr, "Usage: %s [options] [mode] <uifile>\n\n" + "Convert a UI file to version 4:\n" + " %s [options] -convert <uifile>\n" + "Generate declaration:\n" + " %s [options] <uifile>\n" + "\t<uiheaderfile> name of the data file\n" + " %s [options] -decl <uiheaderfile> <uifile>\n" + "\t<uiheaderfile> name of the data file\n" + " %s [options] -wrap <converteduifile> <uifile>\n" + "\t<converteduifile> name of the converted ui file\n" + "Generate implementation:\n" + " %s [options] -impl <headerfile> <uifile>\n" + "\t<headerfile> name of the declaration file\n" + "Generate image collection:\n" + " %s [options] -embed <project> <image1> <image2> <image3> ...\n" + "or\n" + " %s [options] -embed <project> -f <temporary file containing image names>\n" + "\t<project> project name\n" + "\t<image[1-N]> image files\n" + "Generate subclass declaration:\n" + " %s [options] -subdecl <subclassname> <baseclassheaderfile> <uifile>\n" + "\t<subclassname> name of the subclass to generate\n" + "\t<baseclassheaderfile> declaration file of the baseclass\n" + "Generate subclass implementation:\n" + " %s [options] -subimpl <subclassname> <subclassheaderfile> <uifile>\n" + "\t<subclassname> name of the subclass to generate\n" + "\t<subclassheaderfile> declaration file of the subclass\n" + "Options:\n" + "\t-o file Write output to file rather than stdout\n" + "\t-extract qrcFile Create resource file and extract embedded images into \"image\" dir\n" + "\t-pch file Add #include \"file\" as the first statement in implementation\n" + "\t-nofwd Omit forward declarations of custom classes\n" + "\t-no-implicit-includes Do not generate #include-directives for custom classes\n" + "\t-nounload Don't unload plugins after processing\n" + "\t-tr func Use func() instead of tr() for i18n\n" + "\t-L path Additional plugin search path\n" + "\t-version Display version of uic\n" + "\t-help Display this information\n" + , argv[0], argv[0], argv[0], argv[0], argv[0], argv[0], argv[0], argv[0], argv[0], argv[0] + ); + return 1; + } + + if (imagecollection_tmpfile) { + QFile ifile(QFile::decodeName(image_tmpfile)); + if (ifile.open(QIODevice::ReadOnly)) { + QTextStream ts(&ifile); + QString s = ts.read(); + s = s.simplified(); + images = s.split(QLatin1Char(' ')); + for (QStringList::Iterator it = images.begin(); it != images.end(); ++it) + *it = (*it).simplified(); + } + } + + QFile fileOut; + if (!outputFile.isEmpty()) { + fileOut.setFileName(QFile::decodeName(outputFile)); + if (!fileOut.open(QIODevice::WriteOnly)) { + fprintf(stderr, "%s: Could not open output file '%s'\n", argv[0], outputFile.data()); + return 1; + } + } else { + fileOut.open(QIODevice::WriteOnly, stdout); + } + + QTextStream out(&fileOut); + + Ui3Reader ui3(out); + ui3.setExtractImages(extract, qrcOutputFile); + + if (projectName && imagecollection) { + out.setEncoding(QTextStream::Latin1); + ui3.embed(projectName, images); + return 0; + } + + out.setEncoding(QTextStream::UnicodeUTF8); + + QFile file(QFile::decodeName(fileName)); + if (!file.open(QIODevice::ReadOnly)) { + fprintf(stderr, "%s: Could not open file '%s'\n", argv[0], fileName); + return 1; + } + + QDomDocument doc; + QString errMsg; + int errLine; + if (!doc.setContent(&file, &errMsg, &errLine)) { + fprintf(stderr, "%s: Failed to parse %s: %s in line %d\n", argv[0], fileName, errMsg.latin1(), errLine); + return 1; + } + + QDomElement e = doc.firstChild().toElement(); + double version = e.attribute(QLatin1String("version"), QLatin1String("3.0")).toDouble(); + + if (version > 3.3) { + fprintf(stderr, "%s: File generated with too recent version of Qt Designer (%s vs. %s)\n", + argv[0], e.attribute(QLatin1String("version")).latin1(), "3.3"); + return 1; + } + + DomTool::fixDocument(doc); + + if (fix) { + out << doc.toString(); + return 0; + } + + if (imagecollection) { + out.setEncoding(QTextStream::Latin1); + ui3.embed(projectName, images); + return 0; + } else if (deps) { + QStringList globalIncludes, localIncludes; + ui3.computeDeps(e, globalIncludes, localIncludes, impl); + + foreach (QString i, globalIncludes) + printf("%s\n", i.toLatin1().constData()); + + foreach (QString i, localIncludes) + printf("%s\n", i.toLatin1().constData()); + + if (impl) + printf("%s\n", headerFile); + + return 0; + } else if (convert) { + ui3.generateUi4(QFile::decodeName(fileName), QFile::decodeName(outputFile), doc, implicitIncludes); + return 0; + } + + QString protector; + if (subcl && className && !impl) + protector = QString::fromUtf8(className).toUpper() + QLatin1String("_H"); + + if (!protector.isEmpty()) { + out << "#ifndef " << protector << endl; + out << "#define " << protector << endl; + } + + if (!pchFile.isEmpty() && impl) { + out << "#include \"" << pchFile << "\" // PCH include" << endl; + } + + if (headerFile) { + out << "#include \"" << headerFile << "\"" << endl << endl; + } + + QString convertedUi; + if (wrap) { + convertedUi = QFile::decodeName(convertedUiFile); + int pos = convertedUi.lastIndexOf(QLatin1String(".ui")); + if (pos > 0) { + convertedUi = convertedUi.mid(0, pos); + convertedUi += QLatin1String(".h"); + } + convertedUi = QLatin1String("ui_") + convertedUi; + } + + ui3.generate(QFile::decodeName(fileName), + QFile::decodeName(outputFile), + doc, + !impl, + subcl, + QString::fromUtf8(trmacro), + QString::fromUtf8(className), + nofwd, + implicitIncludes, + convertedUi); + + if (!protector.isEmpty()) { + out << endl; + out << "#endif // " << protector << endl; + } + + if (fileOut.error() != QFile::NoError) { + fprintf(stderr, "%s: Error writing to file\n", argv[0]); + if (!outputFile.isEmpty()) + remove(outputFile); + } + + return 0; +} + +QT_END_NAMESPACE + +int main(int argc, char * argv[]) +{ + return QT_PREPEND_NAMESPACE(runUic3(argc, argv)); +} diff --git a/src/tools/uic3/object.cpp b/src/tools/uic3/object.cpp new file mode 100644 index 0000000..b20f3c4 --- /dev/null +++ b/src/tools/uic3/object.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "ui3reader.h" +#include "parser.h" +#include "domtool.h" +#include "globaldefs.h" +#include <QRegExp> +#include <QStringList> +#include <QtDebug> + +QT_BEGIN_NAMESPACE + +/*! Extracts a named object property from \a e. + */ +QDomElement Ui3Reader::getObjectProperty( const QDomElement& e, const QString& name ) +{ + QDomElement n; + for ( n = e.firstChild().toElement(); + !n.isNull(); + n = n.nextSibling().toElement() ) { + if ( n.tagName() == QLatin1String("property") && n.toElement().attribute(QLatin1String("name")) == name ) + return n; + } + return n; +} + +QT_END_NAMESPACE diff --git a/src/tools/uic3/parser.cpp b/src/tools/uic3/parser.cpp new file mode 100644 index 0000000..744dd30 --- /dev/null +++ b/src/tools/uic3/parser.cpp @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "parser.h" +#include <QObject> +#include <QStringList> + +QT_BEGIN_NAMESPACE + +QString Parser::cleanArgs(const QString &func) +{ + QString slot(func); + int begin = slot.indexOf(QLatin1String("(")) + 1; + QString args = slot.mid(begin); + args = args.left(args.indexOf(QLatin1String(")"))); + QStringList lst = args.split(QLatin1Char(',')); + QString res = slot.left(begin); + for (QStringList::Iterator it = lst.begin(); it != lst.end(); ++it) { + if (it != lst.begin()) + res += QLatin1String(","); + QString arg = *it; + int pos = 0; + if ((pos = arg.indexOf(QLatin1Char('&'))) != -1) { + arg = arg.left(pos + 1); + } else if ((pos = arg.indexOf(QLatin1Char('*'))) != -1) { + arg = arg.left(pos + 1); + } else { + arg = arg.simplified(); + if ((pos = arg.indexOf(QLatin1Char(':'))) != -1) + arg = arg.left(pos).simplified() + QLatin1String(":") + arg.mid(pos + 1).simplified(); + QStringList l = arg.split(QLatin1Char(' ')); + if (l.count() == 2) { + if (l[0] != QLatin1String("const") + && l[0] != QLatin1String("unsigned") + && l[0] != QLatin1String("var")) + arg = l[0]; + } else if (l.count() == 3) { + arg = l[0] + QLatin1String(" ") + l[1]; + } + } + res += arg; + } + res += QLatin1String(")"); + return res; +} + +QT_END_NAMESPACE diff --git a/src/tools/uic3/parser.h b/src/tools/uic3/parser.h new file mode 100644 index 0000000..32eb2f7 --- /dev/null +++ b/src/tools/uic3/parser.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PARSER_H +#define PARSER_H + +#include <QString> + +QT_BEGIN_NAMESPACE + +class Parser +{ +public: + static QString cleanArgs( const QString &func ); +}; + +QT_END_NAMESPACE + +#endif // PARSER_H diff --git a/src/tools/uic3/qt3to4.cpp b/src/tools/uic3/qt3to4.cpp new file mode 100644 index 0000000..9e5b64b --- /dev/null +++ b/src/tools/uic3/qt3to4.cpp @@ -0,0 +1,225 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qt3to4.h" + +#include <QApplication> +#include <QDir> +#include <QFile> +#include <QHash> +#include <QLibraryInfo> +#include <QXmlDefaultHandler> +#include <QXmlSimpleReader> + +QT_BEGIN_NAMESPACE + +class ContentHandler: public QXmlDefaultHandler +{ +public: + typedef QPair<QString, QString> Rule; + typedef QList<Rule> RuleList; + +public: + ContentHandler() {} + + inline RuleList renamedHeaders() const + { return rules(QString::fromLatin1("RenamedHeader")); } + + inline RuleList renamedClasses() const + { return rules(QString::fromLatin1("RenamedClass")); } + + inline RuleList renamedEnums() const + { return rules(QString::fromLatin1("RenamedEnumvalue")); } + + inline RuleList rules(const QString &kind) const + { return m_rules.value(kind); } + + virtual bool startDocument() + { + m_rules.clear(); + m_state.current.clear(); + m_state.kind.clear(); + m_state.q3.clear(); + m_state.q4.clear(); + + return true; + } + + virtual bool startElement(const QString &, const QString &, const QString &qName, const QXmlAttributes &attrs) + { + if (qName == QLatin1String("item")) { + m_state.kind = attrs.value(QLatin1String("Type")); + + m_state.current.clear(); + m_state.q3.clear(); + m_state.q4.clear(); + + if (!m_rules.contains(m_state.kind)) + m_rules[m_state.kind].clear(); + + return true; + } + + return true; // ### only if it is a valid tag + } + + + virtual bool endElement(const QString &, const QString &, const QString &qName) + { + if (qName == QLatin1String("Qt3")) { + m_state.q3 = m_state.current.trimmed(); + } else if (qName == QLatin1String("Qt4")) { + m_state.q4 = m_state.current.trimmed(); + } else if (qName == QLatin1String("item") + && (m_state.kind == QLatin1String("RenamedHeader") + || m_state.kind == QLatin1String("RenamedEnumvalue") + || m_state.kind == QLatin1String("RenamedClass"))) { + Rule r(m_state.q3, m_state.q4); + m_rules[m_state.kind].append(r); + } + + m_state.current.clear(); + return true; + } + + virtual bool characters(const QString &ch) + { m_state.current += ch; return true; } + + virtual bool error(const QXmlParseException &e) + { Q_UNUSED(e); Q_ASSERT(0); return true; } + + virtual bool fatalError(const QXmlParseException &e) + { Q_UNUSED(e); Q_ASSERT(0); return true; } + + virtual bool warning(const QXmlParseException &e) + { Q_UNUSED(e); Q_ASSERT(0); return true; } + +private: + QHash<QString, RuleList> m_rules; + + struct state + { + QString current; + QString kind; + QString q3; + QString q4; + } m_state; +}; + +void Porting::readXML(RuleList *renamedHeaders, RuleList *renamedClasses, RuleList *renamedEnums) +{ + QString fileName = QLatin1String("q3porting.xml"); + QString filePath; + //check QLibraryInfo::DataPath/filename + filePath = QDir::cleanPath(QLibraryInfo::location(QLibraryInfo::DataPath) + QLatin1String("/") + fileName) ; + + //check QLibraryInfo::PrefixPath/tools/porting/src/filename + if (!QFile::exists(filePath)) + filePath = QDir::cleanPath(QLibraryInfo::location(QLibraryInfo::PrefixPath) + QLatin1String("/tools/porting/src/") + fileName); + + // for bootstrapping, look in the rules file in a location + // relative to where it would be in the source tree + if (!QFile::exists(filePath)) + filePath = QDir::cleanPath(QApplication::instance()->applicationDirPath() + QLatin1String("/../tools/porting/src/") + fileName); + + if (!QFile::exists(filePath)) { + fprintf(stderr, "Error: Could not find rules file: %s\n", fileName.toLatin1().constData()); + Q_ASSERT(0); + } + + ContentHandler handler; + + QXmlSimpleReader reader; + reader.setContentHandler(&handler); + reader.setErrorHandler(&handler); + + QFile file(filePath); + file.open(QFile::ReadOnly); + + QXmlInputSource source(file); + bool ok = reader.parse(&source); + Q_UNUSED(ok); + Q_ASSERT(ok); + + if (renamedHeaders) + *renamedHeaders = handler.renamedHeaders(); + if (renamedClasses) + *renamedClasses = handler.renamedClasses(); + if (renamedEnums) + *renamedEnums = handler.renamedEnums(); + +} + +Porting::Porting() +{ + readXML(&m_renamedHeaders, &m_renamedClasses, &m_renamedEnums); +} + +int Porting::findRule(const RuleList &rules, const QString &q3) +{ + for (int i=0; i<rules.count(); ++i) + if (rules.at(i).first == q3) + return i; + return -1; +} + +QString Porting::renameHeader(const QString &headerName) const +{ + int index = findRule(m_renamedHeaders, headerName); + return index == -1 ? headerName : m_renamedHeaders.at(index).second; +} + +QString Porting::renameClass(const QString &className) const +{ + if (className == QLatin1String("QSplitter")) // We don't want a Q3Splitter, ever! + return className; + + int index = findRule(m_renamedClasses, className); + return index == -1 ? className : m_renamedClasses.at(index).second; +} + +QString Porting::renameEnumerator(const QString &enumName) const +{ + int index = findRule(m_renamedEnums, enumName); + return index == -1 ? QString() : m_renamedEnums.at(index).second; +} + +QT_END_NAMESPACE diff --git a/src/tools/uic3/qt3to4.h b/src/tools/uic3/qt3to4.h new file mode 100644 index 0000000..806a209 --- /dev/null +++ b/src/tools/uic3/qt3to4.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3TO4_H +#define QT3TO4_H + +#include <QString> +#include <QList> +#include <QPair> + +QT_BEGIN_NAMESPACE + +class Porting +{ +public: + typedef QPair<QString, QString> Rule; + typedef QList<Rule> RuleList; + +public: + Porting(); + + inline RuleList renamedHeaders() const + { return m_renamedHeaders; } + + inline RuleList renamedClasses() const + { return m_renamedClasses; } + + QString renameHeader(const QString &headerName) const; + QString renameClass(const QString &className) const; + QString renameEnumerator(const QString &enumName) const; + +protected: + static void readXML(RuleList *renamedHeaders, RuleList *renamedClasses, RuleList *renamedEnums); + static int findRule(const RuleList &rules, const QString &q3); + +private: + RuleList m_renamedHeaders; + RuleList m_renamedClasses; + RuleList m_renamedEnums; +}; + +QT_END_NAMESPACE + +#endif // QT3TO4_H diff --git a/src/tools/uic3/subclassing.cpp b/src/tools/uic3/subclassing.cpp new file mode 100644 index 0000000..e590ab7 --- /dev/null +++ b/src/tools/uic3/subclassing.cpp @@ -0,0 +1,362 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "ui3reader.h" +#include "parser.h" +#include "domtool.h" +#include "globaldefs.h" +#include <QFile> +#include <QStringList> +#include <QDateTime> +#include <QRegExp> +#include <stdio.h> +#include <stdlib.h> + +QT_BEGIN_NAMESPACE + +/*! + Creates a declaration ( headerfile ) for a subclass \a subClass + of the form given in \a e + + \sa createSubImpl() + */ +void Ui3Reader::createSubDecl( const QDomElement &e, const QString& subClass ) +{ + QDomElement n; + QDomNodeList nl; + int i; + + QString objClass = getClassName( e ); + if ( objClass.isEmpty() ) + return; + + out << "class " << subClass << " : public " << nameOfClass << endl; + out << "{" << endl; + +/* tmake ignore Q_OBJECT */ + out << " Q_OBJECT" << endl; + out << endl; + out << "public:" << endl; + + // constructor + if ( objClass == QLatin1String("QDialog") || objClass == QLatin1String("QWizard") ) { + out << " " << subClass << "( QWidget* parent = 0, const char* name = 0, bool modal = false, Qt::WindowFlags fl = 0 );" << endl; + } else { // standard QWidget + out << " " << subClass << "( QWidget* parent = 0, const char* name = 0, Qt::WindowFlags fl = 0 );" << endl; + } + + // destructor + out << " ~" << subClass << "();" << endl; + out << endl; + + // find additional functions + QStringList publicSlots, protectedSlots, privateSlots; + QStringList publicSlotTypes, protectedSlotTypes, privateSlotTypes; + QStringList publicSlotSpecifier, protectedSlotSpecifier, privateSlotSpecifier; + QStringList publicFuncts, protectedFuncts, privateFuncts; + QStringList publicFunctRetTyp, protectedFunctRetTyp, privateFunctRetTyp; + QStringList publicFunctSpec, protectedFunctSpec, privateFunctSpec; + + nl = e.parentNode().toElement().elementsByTagName(QLatin1String("slot")); + for ( i = 0; i < (int) nl.length(); i++ ) { + n = nl.item(i).toElement(); + if ( n.parentNode().toElement().tagName() != QLatin1String("slots") + && n.parentNode().toElement().tagName() != QLatin1String("connections") ) + continue; + if ( n.attribute(QLatin1String("language"), QLatin1String("C++")) != QLatin1String("C++") ) + continue; + QString returnType = n.attribute(QLatin1String("returnType"), QLatin1String("void")); + QString functionName = n.firstChild().toText().data().trimmed(); + if ( functionName.endsWith(QLatin1String(";"))) + functionName = functionName.left( functionName.length() - 1 ); + QString specifier = n.attribute(QLatin1String("specifier")); + QString access = n.attribute(QLatin1String("access")); + if ( access == QLatin1String("protected") ) { + protectedSlots += functionName; + protectedSlotTypes += returnType; + protectedSlotSpecifier += specifier; + } else if ( access == QLatin1String("private") ) { + privateSlots += functionName; + privateSlotTypes += returnType; + privateSlotSpecifier += specifier; + } else { + publicSlots += functionName; + publicSlotTypes += returnType; + publicSlotSpecifier += specifier; + } + } + + nl = e.parentNode().toElement().elementsByTagName(QLatin1String("function")); + for ( i = 0; i < (int) nl.length(); i++ ) { + n = nl.item(i).toElement(); + if ( n.parentNode().toElement().tagName() != QLatin1String("functions") ) + continue; + if ( n.attribute(QLatin1String("language"), QLatin1String("C++")) != QLatin1String("C++") ) + continue; + QString returnType = n.attribute(QLatin1String("returnType"), QLatin1String("void")); + QString functionName = n.firstChild().toText().data().trimmed(); + if ( functionName.endsWith(QLatin1String(";")) ) + functionName = functionName.left( functionName.length() - 1 ); + QString specifier = n.attribute(QLatin1String("specifier")); + QString access = n.attribute(QLatin1String("access")); + if ( access == QLatin1String("protected") ) { + protectedFuncts += functionName; + protectedFunctRetTyp += returnType; + protectedFunctSpec += specifier; + } else if ( access == QLatin1String("private") ) { + privateFuncts += functionName; + privateFunctRetTyp += returnType; + privateFunctSpec += specifier; + } else { + publicFuncts += functionName; + publicFunctRetTyp += returnType; + publicFunctSpec += specifier; + } + } + + if ( !publicFuncts.isEmpty() ) + writeFunctionsSubDecl( publicFuncts, publicFunctRetTyp, publicFunctSpec ); + + // create public additional slots + if ( !publicSlots.isEmpty() ) { + out << "public slots:" << endl; + writeFunctionsSubDecl( publicSlots, publicSlotTypes, publicSlotSpecifier ); + } + + if ( !protectedFuncts.isEmpty() ) { + out << "protected:" << endl; + writeFunctionsSubDecl( protectedFuncts, protectedFunctRetTyp, protectedFunctSpec ); + } + + // create protected additional slots + if ( !protectedSlots.isEmpty() ) { + out << "protected slots:" << endl; + writeFunctionsSubDecl( protectedSlots, protectedSlotTypes, protectedSlotSpecifier ); + } + + if ( !privateFuncts.isEmpty() ) { + out << "private:" << endl; + writeFunctionsSubDecl( privateFuncts, privateFunctRetTyp, privateFunctSpec ); + } + + // create private additional slots + if ( !privateSlots.isEmpty() ) { + out << "private slots:" << endl; + writeFunctionsSubDecl( privateSlots, privateSlotTypes, privateSlotSpecifier ); + } + out << "};" << endl; +} + +void Ui3Reader::writeFunctionsSubDecl( const QStringList &fuLst, const QStringList &typLst, const QStringList &specLst ) +{ + QStringList::ConstIterator it, it2, it3; + for ( it = fuLst.begin(), it2 = typLst.begin(), it3 = specLst.begin(); + it != fuLst.end(); ++it, ++it2, ++it3 ) { + QString type = fixDeclaration(*it2); + if ( type.isEmpty() ) + type = QLatin1String("void"); + if ( *it3 == QLatin1String("non virtual") ) + continue; + out << " " << type << " " << fixDeclaration(*it) << ";" << endl; + } + out << endl; +} + +/*! + Creates an implementation for a subclass \a subClass of the form + given in \a e + + \sa createSubDecl() + */ +void Ui3Reader::createSubImpl( const QDomElement &e, const QString& subClass ) +{ + QDomElement n; + QDomNodeList nl; + int i; + + QString objClass = getClassName( e ); + if ( objClass.isEmpty() ) + return; + + // constructor + if ( objClass == QLatin1String("QDialog") || objClass == QLatin1String("QWizard") ) { + out << "/* " << endl; + out << " * Constructs a " << subClass << " which is a child of 'parent', with the " << endl; + out << " * name 'name' and widget flags set to 'f' " << endl; + out << " *" << endl; + out << " * The " << objClass.mid(1).toLower() << " will by default be modeless, unless you set 'modal' to" << endl; + out << " * true to construct a modal " << objClass.mid(1).toLower() << "." << endl; + out << " */" << endl; + out << subClass << "::" << subClass << "( QWidget* parent, const char* name, bool modal, Qt::WindowFlags fl )" << endl; + out << " : " << nameOfClass << "( parent, name, modal, fl )" << endl; + } else { // standard QWidget + out << "/* " << endl; + out << " * Constructs a " << subClass << " which is a child of 'parent', with the " << endl; + out << " * name 'name' and widget flags set to 'f' " << endl; + out << " */" << endl; + out << subClass << "::" << subClass << "( QWidget* parent, const char* name, Qt::WindowFlags fl )" << endl; + out << " : " << nameOfClass << "( parent, name, fl )" << endl; + } + out << "{" << endl; + out << "}" << endl; + out << endl; + + // destructor + out << "/* " << endl; + out << " * Destroys the object and frees any allocated resources" << endl; + out << " */" << endl; + out << subClass << "::~" << subClass << "()" << endl; + out << "{" << endl; + out << " // no need to delete child widgets, Qt does it all for us" << endl; + out << "}" << endl; + out << endl; + + + // find additional functions + QStringList publicSlots, protectedSlots, privateSlots; + QStringList publicSlotTypes, protectedSlotTypes, privateSlotTypes; + QStringList publicSlotSpecifier, protectedSlotSpecifier, privateSlotSpecifier; + QStringList publicFuncts, protectedFuncts, privateFuncts; + QStringList publicFunctRetTyp, protectedFunctRetTyp, privateFunctRetTyp; + QStringList publicFunctSpec, protectedFunctSpec, privateFunctSpec; + + nl = e.parentNode().toElement().elementsByTagName(QLatin1String("slot")); + for ( i = 0; i < (int) nl.length(); i++ ) { + n = nl.item(i).toElement(); + if ( n.parentNode().toElement().tagName() != QLatin1String("slots") + && n.parentNode().toElement().tagName() != QLatin1String("connections") ) + continue; + if ( n.attribute(QLatin1String("language"), QLatin1String("C++")) != QLatin1String("C++") ) + continue; + QString returnType = n.attribute(QLatin1String("returnType"), QLatin1String("void")); + QString functionName = n.firstChild().toText().data().trimmed(); + if ( functionName.endsWith(QLatin1String(";")) ) + functionName = functionName.left( functionName.length() - 1 ); + QString specifier = n.attribute(QLatin1String("specifier")); + QString access = n.attribute(QLatin1String("access")); + if ( access == QLatin1String("protected") ) { + protectedSlots += functionName; + protectedSlotTypes += returnType; + protectedSlotSpecifier += specifier; + } else if ( access == QLatin1String("private") ) { + privateSlots += functionName; + privateSlotTypes += returnType; + privateSlotSpecifier += specifier; + } else { + publicSlots += functionName; + publicSlotTypes += returnType; + publicSlotSpecifier += specifier; + } + } + + nl = e.parentNode().toElement().elementsByTagName(QLatin1String("function")); + for ( i = 0; i < (int) nl.length(); i++ ) { + n = nl.item(i).toElement(); + if ( n.parentNode().toElement().tagName() != QLatin1String("functions") ) + continue; + if ( n.attribute(QLatin1String("language"), QLatin1String("C++")) != QLatin1String("C++") ) + continue; + QString returnType = n.attribute(QLatin1String("returnType"), QLatin1String("void")); + QString functionName = n.firstChild().toText().data().trimmed(); + if ( functionName.endsWith(QLatin1String(";")) ) + functionName = functionName.left( functionName.length() - 1 ); + QString specifier = n.attribute(QLatin1String("specifier")); + QString access = n.attribute(QLatin1String("access")); + if ( access == QLatin1String("protected") ) { + protectedFuncts += functionName; + protectedFunctRetTyp += returnType; + protectedFunctSpec += specifier; + } else if ( access == QLatin1String("private") ) { + privateFuncts += functionName; + privateFunctRetTyp += returnType; + privateFunctSpec += specifier; + } else { + publicFuncts += functionName; + publicFunctRetTyp += returnType; + publicFunctSpec += specifier; + } + } + + if ( !publicFuncts.isEmpty() ) + writeFunctionsSubImpl( publicFuncts, publicFunctRetTyp, publicFunctSpec, subClass, QLatin1String("public function")); + + // create stubs for public additional slots + if ( !publicSlots.isEmpty() ) + writeFunctionsSubImpl( publicSlots, publicSlotTypes, publicSlotSpecifier, subClass, QLatin1String("public slot")); + + if ( !protectedFuncts.isEmpty() ) + writeFunctionsSubImpl( protectedFuncts, protectedFunctRetTyp, protectedFunctSpec, subClass, QLatin1String("protected function")); + + // create stubs for protected additional slots + if ( !protectedSlots.isEmpty() ) + writeFunctionsSubImpl( protectedSlots, protectedSlotTypes, protectedSlotSpecifier, subClass, QLatin1String("protected slot")); + + if ( !privateFuncts.isEmpty() ) + writeFunctionsSubImpl( privateFuncts, privateFunctRetTyp, privateFunctSpec, subClass, QLatin1String("private function")); + + // create stubs for private additional slots + if ( !privateSlots.isEmpty() ) + writeFunctionsSubImpl( privateSlots, privateSlotTypes, privateSlotSpecifier, subClass, QLatin1String("private slot")); +} + +void Ui3Reader::writeFunctionsSubImpl( const QStringList &fuLst, const QStringList &typLst, const QStringList &specLst, + const QString &subClass, const QString &descr ) +{ + QStringList::ConstIterator it, it2, it3; + for ( it = fuLst.begin(), it2 = typLst.begin(), it3 = specLst.begin(); + it != fuLst.end(); ++it, ++it2, ++it3 ) { + QString type = fixDeclaration(*it2); + if ( type.isEmpty() ) + type = QLatin1String("void"); + if ( *it3 == QLatin1String("non virtual") ) + continue; + out << "/*" << endl; + out << " * " << descr << endl; + out << " */" << endl; + out << type << " " << subClass << "::" << fixDeclaration(*it) << endl; + out << "{" << endl; + out << " qWarning( \"" << subClass << "::" << fixDeclaration(*it) << " not yet implemented!\" );" << endl; + out << "}" << endl << endl; + } + out << endl; +} + +QT_END_NAMESPACE diff --git a/src/tools/uic3/ui3reader.cpp b/src/tools/uic3/ui3reader.cpp new file mode 100644 index 0000000..1ba4b2f --- /dev/null +++ b/src/tools/uic3/ui3reader.cpp @@ -0,0 +1,639 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "ui3reader.h" +#include "parser.h" +#include "domtool.h" +#include "ui4.h" +#include "widgetinfo.h" +#include "globaldefs.h" +#include "qt3to4.h" + +#include <QFile> +#include <QDateTime> +#include <QRegExp> +#include <QXmlStreamWriter> +#include <QtDebug> +#include <stdio.h> +#include <stdlib.h> + +QT_BEGIN_NAMESPACE + +bool Ui3Reader::isMainWindow = false; + +static QString lineColDebug(int line, int col) +{ + if (line >= 0) { + const QString ret = QString::fromLatin1("Line: %1%2"); + return ret.arg(line).arg(col >= 0 ? QString::fromLatin1(" Column: %1").arg(col) : QString()); + } + return QString(); +} + +void Ui3Reader::errorInvalidProperty(const QString &propertyName, const QString &widgetName, const QString &widgetClass, int line, int col) +{ + fprintf(stderr, "uic3: property `%s' for widget `%s' of type `%s' is not supported. %s\n", + propertyName.toLatin1().constData(), + widgetName.toLatin1().constData(), + widgetClass.toLatin1().constData(), + lineColDebug(line, col).toLocal8Bit().constData()); +} + +void Ui3Reader::errorInvalidSignal(const QString &signal, const QString &widgetName, const QString &widgetClass, int line, int col) +{ + fprintf(stderr, "uic3: signal `%s' for widget `%s' of type `%s' is not supported; connection may fail. %s\n", + signal.toLatin1().constData(), widgetName.toLatin1().constData(), + widgetClass.toLatin1().constData(), + lineColDebug(line, col).toLocal8Bit().constData()); +} + +void Ui3Reader::errorInvalidSlot(const QString &slot, const QString &widgetName, const QString &widgetClass, int line, int col) +{ + fprintf(stderr, "uic3: slot `%s' for widget `%s' of type `%s' is not supported; connection may fail. %s\n", + slot.toLatin1().constData(), + widgetName.toLatin1().constData(), + widgetClass.toLatin1().constData(), + lineColDebug(line, col).toLocal8Bit().constData()); +} + +QString Ui3Reader::getComment(const QDomNode& n) +{ + QDomNode child = n.firstChild(); + while (!child.isNull()) { + if (child.toElement().tagName() == QLatin1String("comment")) + return child.toElement().firstChild().toText().data(); + child = child.nextSibling(); + } + return QString(); +} + +QString Ui3Reader::mkBool(bool b) +{ + return b ? QLatin1String("true") : QLatin1String("false"); +} + +QString Ui3Reader::mkBool(const QString& s) +{ + return mkBool(s == QLatin1String("true") || s == QLatin1String("1")); +} + +bool Ui3Reader::toBool(const QString& s) +{ + return s == QLatin1String("true") || s.toInt() != 0; +} + +QString Ui3Reader::fixString(const QString &str, bool encode) +{ + QString s; + if (!encode) { + s = str; + s.replace(QLatin1String("\\"), QLatin1String("\\\\")); + s.replace(QLatin1String("\""), QLatin1String("\\\"")); + s.replace(QLatin1String("\r"), QLatin1String("")); + s.replace(QLatin1String("\n"), QLatin1String("\\n\"\n\"")); + } else { + QByteArray utf8 = str.utf8(); + const int l = utf8.length(); + for (int i = 0; i < l; ++i) + s += QLatin1String("\\x") + QString::number((uchar)utf8[i], 16); + } + + return QLatin1String("\"") + s + QLatin1String("\""); +} + +QString Ui3Reader::trcall(const QString& sourceText, const QString& comment) +{ + if (sourceText.isEmpty() && comment.isEmpty()) + return QLatin1String("QString()"); + + QString t = trmacro; + bool encode = false; + if (t.isNull()) { + t = QLatin1String("tr"); + for (int i = 0; i < (int) sourceText.length(); i++) { + if (sourceText[i].unicode() >= 0x80) { + t = QLatin1String("trUtf8"); + encode = true; + break; + } + } + } + + if (comment.isEmpty()) { + return t + QLatin1String("(") + fixString(sourceText, encode) + QLatin1String(")"); + } else { + return t + QLatin1String("(") + + fixString(sourceText, encode) + + QLatin1String(", ") + + fixString(comment, encode) + QLatin1String(")"); + } +} + +QString Ui3Reader::mkStdSet(const QString& prop) +{ + return QLatin1String("set") + prop[0].toUpper() + prop.mid(1); +} + +void Ui3Reader::init() +{ + outputFileName.clear(); + trmacro.clear(); + nofwd = false; + + fileName.clear(); + writeFunctImpl = true; + defMargin = BOXLAYOUT_DEFAULT_MARGIN; + defSpacing = BOXLAYOUT_DEFAULT_SPACING; + externPixmaps = false; + indent = QLatin1String(" "); // default indent + + item_used = cg_used = pal_used = 0; + + layouts.clear(); + layouts << QLatin1String("hbox") << QLatin1String("vbox") << QLatin1String("grid"); + tags = layouts; + tags << QLatin1String("widget"); + + nameOfClass.clear(); + namespaces.clear(); + bareNameOfClass.clear(); +} + +QDomElement Ui3Reader::parse(const QDomDocument &doc) +{ + root = doc.firstChild().toElement(); + widget = QDomElement(); + + pixmapLoaderFunction = getPixmapLoaderFunction(doc.firstChild().toElement()); + nameOfClass = getFormClassName(doc.firstChild().toElement()); + + uiFileVersion = doc.firstChild().toElement().attribute(QLatin1String("version")); + stdsetdef = toBool(doc.firstChild().toElement().attribute(QLatin1String("stdsetdef"))); + + if (doc.firstChild().isNull() || doc.firstChild().firstChild().isNull()) + return widget; + + QDomElement e = doc.firstChild().firstChild().toElement(); + while (!e.isNull()) { + if (e.tagName() == QLatin1String("widget")) { + widget = e; + } else if (e.tagName() == QLatin1String("pixmapinproject")) { + externPixmaps = true; + } else if (e.tagName() == QLatin1String("layoutdefaults")) { + defSpacing = e.attribute(QLatin1String("spacing"), defSpacing.toString()); + defMargin = e.attribute(QLatin1String("margin"), defMargin.toString()); + } else if (e.tagName() == QLatin1String("layoutfunctions")) { + defSpacing = e.attribute(QLatin1String("spacing"), defSpacing.toString()); + bool ok; + defSpacing.toInt(&ok); + if (!ok) { + QString buf = defSpacing.toString(); + defSpacing = buf.append(QLatin1String("()")); + } + defMargin = e.attribute(QLatin1String("margin"), defMargin.toString()); + defMargin.toInt(&ok); + if (!ok) { + QString buf = defMargin.toString(); + defMargin = buf.append(QLatin1String("()")); + } + } + e = e.nextSibling().toElement(); + } + + return widget; +} + +Ui3Reader::Ui3Reader(QTextStream &outStream) + : out(outStream), trout(&languageChangeBody) +{ + m_porting = new Porting(); + m_extractImages = false; +} + +Ui3Reader::~Ui3Reader() +{ + delete m_porting; +} + +void Ui3Reader::generate(const QString &fn, const QString &outputFn, + QDomDocument doc, bool decl, bool subcl, const QString &trm, + const QString& subClass, bool omitForwardDecls, bool implicitIncludes, const QString &convertedUiFile) +{ + init(); + + fileName = fn; + outputFileName = outputFn; + trmacro = trm; + nofwd = omitForwardDecls; + + QDomElement e = parse(doc); + + if (nameOfClass.isEmpty()) + nameOfClass = getObjectName(e); + namespaces = nameOfClass.split(QLatin1String("::")); + bareNameOfClass = namespaces.last(); + namespaces.removeLast(); + + if (!convertedUiFile.isEmpty()) { + createWrapperDecl(e, convertedUiFile); + } else if (subcl) { + if (decl) + createSubDecl(e, subClass); + else + createSubImpl(e, subClass); + } else { + if (decl) + createFormDecl(e, implicitIncludes); + else + createFormImpl(e); + } + +} + +void Ui3Reader::generateUi4(const QString &fn, const QString &outputFn, QDomDocument doc, bool implicitIncludes) +{ + init(); + + fileName = fn; + outputFileName = outputFn; + + DomUI *ui = generateUi4(parse(doc), implicitIncludes); + if (!ui) + return; + + if (pixmapLoaderFunction.size()) + ui->setElementPixmapFunction(pixmapLoaderFunction); + + QXmlStreamWriter writer(out.device()); + writer.setAutoFormatting(true); + writer.setAutoFormattingIndent(2); + writer.writeStartDocument(); + ui->write(writer); + writer.writeEndDocument(); + + delete ui; +} + +void Ui3Reader::setTrMacro(const QString &trmacro) +{ + this->trmacro = trmacro; +} + +void Ui3Reader::setForwardDeclarationsEnabled(bool b) +{ + nofwd = !b; +} + +void Ui3Reader::setOutputFileName(const QString &fileName) +{ + outputFileName = fileName; +} + +/*! Extracts a pixmap loader function from \a e + */ +QString Ui3Reader::getPixmapLoaderFunction(const QDomElement& e) +{ + QDomElement n; + for (n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement()) { + if (n.tagName() == QLatin1String("pixmapfunction")) + return n.firstChild().toText().data(); + } + return QString(); +} + + +/*! Extracts the forms class name from \a e + */ +QString Ui3Reader::getFormClassName(const QDomElement& e) +{ + QDomElement n; + QString cn; + for (n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement()) { + if (n.tagName() == QLatin1String("class")) { + QString s = n.firstChild().toText().data(); + int i; + while ((i = s.indexOf(QLatin1Char(' '))) != -1) + s[i] = QLatin1Char('_'); + cn = s; + } + } + return cn; +} + +/*! Extracts a class name from \a e. + */ +QString Ui3Reader::getClassName(const QDomElement& e) +{ + QString s = e.attribute(QLatin1String("class")); + if (s.isEmpty() && e.tagName() == QLatin1String("toolbar")) + s = QLatin1String(QLatin1String("QToolBar")); + else if (s.isEmpty() && e.tagName() == QLatin1String("menubar")) + s = QLatin1String("QMenuBar"); + + return fixClassName(s); +} + +/*! Returns true if database framework code is generated, else false. +*/ + +bool Ui3Reader::isFrameworkCodeGenerated(const QDomElement& e) +{ + QDomElement n = getObjectProperty(e, QLatin1String("frameworkCode")); + if (n.attribute(QLatin1String("name")) == QLatin1String("frameworkCode") && + !DomTool::elementToVariant(n.firstChild().toElement(), QVariant(true)).toBool()) + return false; + return true; +} + +/*! Extracts an object name from \a e. It's stored in the 'name' + property. + */ +QString Ui3Reader::getObjectName(const QDomElement& e) +{ + QDomElement n = getObjectProperty(e, QLatin1String("name")); + if (n.firstChild().toElement().tagName() == QLatin1String("cstring")) + return n.firstChild().toElement().firstChild().toText().data(); + return QString(); +} + +/*! Extracts an layout name from \a e. It's stored in the 'name' + property of the preceding sibling (the first child of a QLayoutWidget). + */ +QString Ui3Reader::getLayoutName(const QDomElement& e) +{ + QDomElement p = e.parentNode().toElement(); + QString name; + + if (getClassName(p) != QLatin1String("QLayoutWidget")) + name = QLatin1String("Layout"); + + QDomElement n = getObjectProperty(p, QLatin1String("name")); + if (n.firstChild().toElement().tagName() == QLatin1String("cstring")) { + name.prepend(n.firstChild().toElement().firstChild().toText().data()); + return name.split(QLatin1String("::")).last(); + } + return e.tagName(); +} + + +QString Ui3Reader::getDatabaseInfo(const QDomElement& e, const QString& tag) +{ + QDomElement n; + QDomElement n1; + int child = 0; + // database info is a stringlist stored in this order + if (tag == QLatin1String("connection")) + child = 0; + else if (tag == QLatin1String("table")) + child = 1; + else if (tag == QLatin1String("field")) + child = 2; + else + return QString(); + n = getObjectProperty(e, QLatin1String("database")); + if (n.firstChild().toElement().tagName() == QLatin1String("stringlist")) { + // find correct stringlist entry + QDomElement n1 = n.firstChild().firstChild().toElement(); + for (int i = 0; i < child && !n1.isNull(); ++i) + n1 = n1.nextSibling().toElement(); + if (n1.isNull()) + return QString(); + return n1.firstChild().toText().data(); + } + return QString(); +} + +static const char* const ColorRole[] = { + "Foreground", "Button", "Light", "Midlight", "Dark", "Mid", + "Text", "BrightText", "ButtonText", "Base", "Background", "Shadow", + "Highlight", "HighlightedText", "Link", "LinkVisited", 0 +}; + + +/*! + Creates a colorgroup with name \a name from the color group \a cg + */ +void Ui3Reader::createColorGroupImpl(const QString& name, const QDomElement& e) +{ + int r = -1; + QDomElement n = e.firstChild().toElement(); + QString color; + + Color white; + white.init(255, 255, 255); + + Color black; + black.init(0, 0, 0); + + while (!n.isNull()) { + if (n.tagName() == QLatin1String("color")) { + r++; + Color col = DomTool::readColor(n); + color = QLatin1String("QColor(%1, %2, %3)"); + color = color.arg(col.red).arg(col.green).arg(col.blue); + if (col == white) + color = QLatin1String("white"); + else if (col == black) + color = QLatin1String("black"); + if (n.nextSibling().toElement().tagName() != QLatin1String("pixmap")) { + out << indent << name << ".setColor(QColorGroup::" << ColorRole[r] << ", " << color << ");" << endl; + } + } else if (n.tagName() == QLatin1String("pixmap")) { + QString pixmap = n.firstChild().toText().data(); + if (!pixmapLoaderFunction.isEmpty()) { + pixmap.prepend(pixmapLoaderFunction + + QLatin1String("(") + + QLatin1String(externPixmaps ? "\"" : "")); + + pixmap.append(QLatin1String(externPixmaps ? "\"" : "") + QLatin1String(")")); + } + out << indent << name << ".setBrush(QColorGroup::" + << ColorRole[r] << ", QBrush(" << color << ", " << pixmap << "));" << endl; + } + n = n.nextSibling().toElement(); + } +} + +/*! + Auxiliary function to load a color group. The colorgroup must not + contain pixmaps. + */ +ColorGroup Ui3Reader::loadColorGroup(const QDomElement &e) +{ + ColorGroup cg; + int r = -1; + QDomElement n = e.firstChild().toElement(); + Color col; + while (!n.isNull()) { + if (n.tagName() == QLatin1String("color")) { + r++; + col = DomTool::readColor(n); + cg.append(qMakePair(r, col)); + } + n = n.nextSibling().toElement(); + } + return cg; +} + +/*! Returns true if the widget properties specify that it belongs to + the database \a connection and \a table. +*/ + +bool Ui3Reader::isWidgetInTable(const QDomElement& e, const QString& connection, const QString& table) +{ + QString conn = getDatabaseInfo(e, QLatin1String("connection")); + QString tab = getDatabaseInfo(e, QLatin1String("table")); + if (conn == connection && tab == table) + return true; + return false; +} + +/*! + Registers all database connections, cursors and forms. +*/ + +void Ui3Reader::registerDatabases(const QDomElement& e) +{ + QDomElement n; + QDomNodeList nl; + int i; + nl = e.parentNode().toElement().elementsByTagName(QLatin1String("widget")); + for (i = 0; i < (int) nl.length(); ++i) { + n = nl.item(i).toElement(); + QString conn = getDatabaseInfo(n, QLatin1String("connection")); + QString tab = getDatabaseInfo(n, QLatin1String("table")); + QString fld = getDatabaseInfo(n, QLatin1String("field")); + if (!conn.isNull()) { + dbConnections += conn; + if (!tab.isNull()) { + dbCursors[conn] += tab; + if (!fld.isNull()) + dbForms[conn] += tab; + } + } + } +} + +/*! + Registers an object with name \a name. + + The returned name is a valid variable identifier, as similar to \a + name as possible and guaranteed to be unique within the form. + + \sa registeredName(), isObjectRegistered() + */ +QString Ui3Reader::registerObject(const QString& name) +{ + if (objectNames.isEmpty()) { + // some temporary variables we need + objectNames += QLatin1String("img"); + objectNames += QLatin1String("item"); + objectNames += QLatin1String("cg"); + objectNames += QLatin1String("pal"); + } + + QString result = name; + int i; + while ((i = result.indexOf(QLatin1Char(' '))) != -1 ) { + result[i] = QLatin1Char('_'); + } + + if (objectNames.contains(result)) { + int i = 2; + while (objectNames.contains(result + QLatin1String("_") + QString::number(i))) + i++; + result += QLatin1String("_"); + result += QString::number(i); + } + objectNames += result; + objectMapper.insert(name, result); + return result; +} + +/*! + Returns the registered name for the original name \a name + or \a name if \a name wasn't registered. + + \sa registerObject(), isObjectRegistered() + */ +QString Ui3Reader::registeredName(const QString& name) +{ + if (!objectMapper.contains(name)) + return name; + return objectMapper[name]; +} + +/*! + Returns whether the object \a name was registered yet or not. + */ +bool Ui3Reader::isObjectRegistered(const QString& name) +{ + return objectMapper.contains(name); +} + +/*! + Unifies the entries in stringlist \a list. Should really be a QStringList feature. + */ +QStringList Ui3Reader::unique(const QStringList& list) +{ + if (list.isEmpty()) + return list; + + QStringList result; + for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it) { + if (!result.contains(*it)) + result += *it; + } + return result; +} + +bool Ui3Reader::isLayout(const QString& name) const +{ + return layoutObjects.contains(name); +} + +void Ui3Reader::setExtractImages(bool extract, const QString &qrcOutputFile) +{ + m_extractImages = extract; + m_qrcOutputFile = qrcOutputFile; +} + +QT_END_NAMESPACE diff --git a/src/tools/uic3/ui3reader.h b/src/tools/uic3/ui3reader.h new file mode 100644 index 0000000..60e0cee --- /dev/null +++ b/src/tools/uic3/ui3reader.h @@ -0,0 +1,233 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef UI3READER_H +#define UI3READER_H + +#include <QDomDocument> +#include <QString> +#include <QStringList> +#include <QMap> +#include <QTextStream> +#include <QVariant> +#include <QByteArray> +#include <QPair> + +QT_BEGIN_NAMESPACE + +class DomUI; +class DomFont; +class DomWidget; +class DomProperty; +class DomLayout; +class DomLayoutItem; +class DomActionGroup; +class Porting; +struct Color; + +typedef QList<QPair<int, Color> > ColorGroup; + +class Ui3Reader +{ +public: + Ui3Reader(QTextStream &stream); + ~Ui3Reader(); + + void computeDeps(const QDomElement &e, QStringList &globalIncludes, QStringList &localIncludes, bool impl = false); + void generateUi4(const QString &fn, const QString &outputFn, QDomDocument doc, bool implicitIncludes); + + void generate(const QString &fn, const QString &outputFn, + QDomDocument doc, bool decl, bool subcl, const QString &trm, + const QString& subclname, bool omitForwardDecls, bool implicitIncludes, const QString &convertedUiFile); + + void embed(const char *project, const QStringList &images); + + void setTrMacro(const QString &trmacro); + void setForwardDeclarationsEnabled(bool b); + void setOutputFileName(const QString &fileName); + + void createFormDecl(const QDomElement &e, bool implicitIncludes); + void createFormImpl(const QDomElement &e); + + void createWrapperDecl(const QDomElement &e, const QString &convertedUiFile); + + void createSubDecl(const QDomElement &e, const QString& subclname); + void createSubImpl(const QDomElement &e, const QString& subclname); + + void createColorGroupImpl(const QString& cg, const QDomElement& e); + ColorGroup loadColorGroup(const QDomElement &e); + + QDomElement getObjectProperty(const QDomElement& e, const QString& name); + QString getPixmapLoaderFunction(const QDomElement& e); + QString getFormClassName(const QDomElement& e); + QString getClassName(const QDomElement& e); + QString getObjectName(const QDomElement& e); + QString getLayoutName(const QDomElement& e); + + QString registerObject(const QString& name); + QString registeredName(const QString& name); + bool isObjectRegistered(const QString& name); + QStringList unique(const QStringList&); + + QString trcall(const QString& sourceText, const QString& comment = QString()); + + QDomElement parse(const QDomDocument &doc); + + void setExtractImages(bool extract, const QString &qrcOutputFile); + +private: + void init(); + + void createWrapperDeclContents(const QDomElement &e); + + void errorInvalidProperty(const QString &propertyName, const QString &widgetName, const QString &widgetClass, + int line, int col); + void errorInvalidSignal(const QString &signal, const QString &widgetName, const QString &widgetClass, + int line, int col); + void errorInvalidSlot(const QString &slot, const QString &widgetName, const QString &widgetClass, + int line, int col); + + DomUI *generateUi4(const QDomElement &e, bool implicitIncludes); + DomWidget *createWidget(const QDomElement &w, const QString &widgetClass = QString()); + void createProperties(const QDomElement &e, QList<DomProperty*> *properties, const QString &className); + void createAttributes(const QDomElement &e, QList<DomProperty*> *properties, const QString &className); + DomLayout *createLayout(const QDomElement &e); + DomLayoutItem *createLayoutItem(const QDomElement &e); + DomProperty *readProperty(const QDomElement &e); + void fixActionGroup(DomActionGroup *g); + QString fixActionProperties(QList<DomProperty*> &properties, bool isActionGroup = false); + + QString fixHeaderName(const QString &headerName) const; + QString fixClassName(const QString &className) const; + QString fixDeclaration(const QString &declaration) const; + QString fixType(const QString &type) const; + QString fixMethod(const QString &method) const; + + QDomElement findDerivedFontProperties(const QDomElement &n) const; + + void fixLayoutMargin(DomLayout *ui_layout); + + QTextStream &out; + QTextOStream trout; + QString languageChangeBody; + QString outputFileName; + QStringList objectNames; + QMap<QString,QString> objectMapper; + QString indent; + QStringList tags; + QStringList layouts; + QString formName; + QString lastItem; + QString trmacro; + bool nofwd; + + struct Buddy + { + Buddy(const QString& k, const QString& b) + : key(k), buddy(b) {} + Buddy(){} // for valuelist + QString key; + QString buddy; + bool operator==(const Buddy& other) const + { return (key == other.key); } + }; + struct CustomInclude + { + QString header; + QString location; + Q_DUMMY_COMPARISON_OPERATOR(CustomInclude) + }; + QList<Buddy> buddies; + + QStringList layoutObjects; + bool isLayout(const QString& name) const; + + uint item_used : 1; + uint cg_used : 1; + uint pal_used : 1; + uint stdsetdef : 1; + uint externPixmaps : 1; + + QString uiFileVersion; + QString nameOfClass; + QStringList namespaces; + QString bareNameOfClass; + QString pixmapLoaderFunction; + + void registerDatabases(const QDomElement& e); + bool isWidgetInTable(const QDomElement& e, const QString& connection, const QString& table); + bool isFrameworkCodeGenerated(const QDomElement& e); + QString getDatabaseInfo(const QDomElement& e, const QString& tag); + void createFormImpl(const QDomElement& e, const QString& form, const QString& connection, const QString& table); + void writeFunctionsDecl(const QStringList &fuLst, const QStringList &typLst, const QStringList &specLst); + void writeFunctionsSubDecl(const QStringList &fuLst, const QStringList &typLst, const QStringList &specLst); + void writeFunctionsSubImpl(const QStringList &fuLst, const QStringList &typLst, const QStringList &specLst, + const QString &subClass, const QString &descr); + QStringList dbConnections; + QMap<QString, QStringList> dbCursors; + QMap<QString, QStringList> dbForms; + + static bool isMainWindow; + static QString mkBool(bool b); + static QString mkBool(const QString& s); + bool toBool(const QString& s); + static QString fixString(const QString &str, bool encode = false); + static bool onlyAscii; + static QString mkStdSet(const QString& prop); + static QString getComment(const QDomNode& n); + QVariant defSpacing, defMargin; + QString fileName; + bool writeFunctImpl; + + QDomElement root; + QDomElement widget; + + QMap<QString, bool> candidateCustomWidgets; + Porting *m_porting; + + bool m_extractImages; + QString m_qrcOutputFile; + QMap<QString, QString> m_imageMap; +}; + +QT_END_NAMESPACE + +#endif // UI3READER_H diff --git a/src/tools/uic3/uic.cpp b/src/tools/uic3/uic.cpp new file mode 100644 index 0000000..d042abd --- /dev/null +++ b/src/tools/uic3/uic.cpp @@ -0,0 +1,341 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "uic.h" +#include "ui4.h" +#include "driver.h" +#include "option.h" +#include "treewalker.h" +#include "validator.h" + +#ifdef QT_UIC_CPP_GENERATOR +#include "cppwriteincludes.h" +#include "cppwritedeclaration.h" +#endif + +#ifdef QT_UIC_JAVA_GENERATOR +#include "javawriteincludes.h" +#include "javawritedeclaration.h" +#endif + +#include <QtXml/QDomDocument> +#include <QtCore/QFileInfo> +#include <QtCore/QRegExp> +#include <QtCore/QTextStream> +#include <QtCore/QDateTime> + +#if defined Q_WS_WIN +#include <qt_windows.h> +#endif + +QT_BEGIN_NAMESPACE + +Uic::Uic(Driver *d) + : drv(d), + out(d->output()), + opt(d->option()), + info(d), + externalPix(true) +{ +} + +Uic::~Uic() +{ +} + +bool Uic::printDependencies() +{ + QString fileName = opt.inputFile; + + QFile f; + if (fileName.isEmpty()) + f.open(stdin, QIODevice::ReadOnly); + else { + f.setFileName(fileName); + if (!f.open(QIODevice::ReadOnly)) + return false; + } + + QDomDocument doc; // ### generalize. share more code with the other tools! + if (!doc.setContent(&f)) + return false; + + QDomElement root = doc.firstChildElement(); + DomUI *ui = new DomUI(); + ui->read(root); + + double version = ui->attributeVersion().toDouble(); + if (version < 4.0) { + delete ui; + + fprintf(stderr, "uic: File generated with too old version of Qt Designer\n"); + return false; + } + + if (DomIncludes *includes = ui->elementIncludes()) { + foreach (DomInclude *incl, includes->elementInclude()) { + QString file = incl->text(); + if (file.isEmpty()) + continue; + + fprintf(stdout, "%s\n", file.toLocal8Bit().constData()); + } + } + + if (DomCustomWidgets *customWidgets = ui->elementCustomWidgets()) { + foreach (DomCustomWidget *customWidget, customWidgets->elementCustomWidget()) { + if (DomHeader *header = customWidget->elementHeader()) { + QString file = header->text(); + if (file.isEmpty()) + continue; + + fprintf(stdout, "%s\n", file.toLocal8Bit().constData()); + } + } + } + + delete ui; + + return true; +} + +void Uic::writeCopyrightHeader(DomUI *ui) +{ + QString comment = ui->elementComment(); + if (comment.size()) + out << "/*\n" << comment << "\n*/\n\n"; + + out << "/********************************************************************************\n"; + out << "** Form generated from reading ui file '" << QFileInfo(opt.inputFile).fileName() << "'\n"; + out << "**\n"; + out << "** Created: " << QDateTime::currentDateTime().toString() << "\n"; + out << "** " << QString::fromLatin1("by: Qt User Interface Compiler version %1\n").arg(QLatin1String(QT_VERSION_STR)); + out << "**\n"; + out << "** WARNING! All changes made in this file will be lost when recompiling ui file!\n"; + out << "********************************************************************************/\n\n"; +} + +bool Uic::write(QIODevice *in) +{ + QDomDocument doc; + if (!doc.setContent(in)) + return false; + + if (option().generator == Option::JavaGenerator) { + // the Java generator ignores header protection + opt.headerProtection = false; + } + + QDomElement root = doc.firstChildElement(); + DomUI *ui = new DomUI(); + ui->read(root); + + double version = ui->attributeVersion().toDouble(); + if (version < 4.0) { + delete ui; + + fprintf(stderr, "uic: File generated with too old version of Qt Designer\n"); + return false; + } + + QString language = ui->attributeLanguage(); + + + bool rtn = false; + + if (option().generator == Option::JavaGenerator) { +#ifdef QT_UIC_JAVA_GENERATOR + if (language.toLower() != QLatin1String("jambi")) { + fprintf(stderr, "uic: File is not a 'jambi' form\n"); + return false; + } + rtn = jwrite (ui); +#else + fprintf(stderr, "uic: option to generate java code not compiled in\n"); +#endif + } else { +#ifdef QT_UIC_CPP_GENERATOR + if (!language.isEmpty() && language.toLower() != QLatin1String("c++")) { + fprintf(stderr, "uic: File is not a 'c++' ui file, language=%s\n", qPrintable(language)); + return false; + } + + rtn = write (ui); +#else + fprintf(stderr, "uic: option to generate cpp code not compiled in\n"); +#endif + } + + delete ui; + + return rtn; +} + +#ifdef QT_UIC_CPP_GENERATOR +bool Uic::write(DomUI *ui) +{ + using namespace CPP; + + if (!ui || !ui->elementWidget()) + return false; + + if (opt.copyrightHeader) + writeCopyrightHeader(ui); + + if (opt.headerProtection) { + writeHeaderProtectionStart(); + out << "\n"; + } + + pixFunction = ui->elementPixmapFunction(); + if (pixFunction == QLatin1String("QPixmap::fromMimeSource")) + pixFunction = QLatin1String("qPixmapFromMimeSource"); + + externalPix = ui->elementImages() == 0; + + info.acceptUI(ui); + cWidgetsInfo.acceptUI(ui); + WriteIncludes writeIncludes(this); + writeIncludes.acceptUI(ui); + + Validator(this).acceptUI(ui); + WriteDeclaration(this, writeIncludes.scriptsActivated()).acceptUI(ui); + + if (opt.headerProtection) + writeHeaderProtectionEnd(); + + return true; +} +#endif + +#ifdef QT_UIC_JAVA_GENERATOR +bool Uic::jwrite(DomUI *ui) +{ + using namespace Java; + + if (!ui || !ui->elementWidget()) + return false; + + if (opt.copyrightHeader) + writeCopyrightHeader(ui); + + pixFunction = ui->elementPixmapFunction(); + if (pixFunction == QLatin1String("QPixmap::fromMimeSource")) + pixFunction = QLatin1String("qPixmapFromMimeSource"); + + externalPix = ui->elementImages() == 0; + + info.acceptUI(ui); + cWidgetsInfo.acceptUI(ui); + WriteIncludes(this).acceptUI(ui); + + Validator(this).acceptUI(ui); + WriteDeclaration(this).acceptUI(ui); + + return true; +} +#endif + +#ifdef QT_UIC_CPP_GENERATOR + +void Uic::writeHeaderProtectionStart() +{ + QString h = drv->headerFileName(); + out << "#ifndef " << h << "\n" + << "#define " << h << "\n"; +} + +void Uic::writeHeaderProtectionEnd() +{ + QString h = drv->headerFileName(); + out << "#endif // " << h << "\n"; +} +#endif + +bool Uic::isMainWindow(const QString &className) const +{ + return customWidgetsInfo()->extends(className, QLatin1String("Q3MainWindow")) + || customWidgetsInfo()->extends(className, QLatin1String("QMainWindow")); +} + +bool Uic::isToolBar(const QString &className) const +{ + return customWidgetsInfo()->extends(className, QLatin1String("Q3ToolBar")) + || customWidgetsInfo()->extends(className, QLatin1String("QToolBar")); +} + +bool Uic::isButton(const QString &className) const +{ + return customWidgetsInfo()->extends(className, QLatin1String("QRadioButton")) + || customWidgetsInfo()->extends(className, QLatin1String("QToolButton")) + || customWidgetsInfo()->extends(className, QLatin1String("QCheckBox")) + || customWidgetsInfo()->extends(className, QLatin1String("QPushButton")) + || customWidgetsInfo()->extends(className, QLatin1String("QCommandLinkButton")); +} + +bool Uic::isContainer(const QString &className) const +{ + return customWidgetsInfo()->extends(className, QLatin1String("QStackedWidget")) + || customWidgetsInfo()->extends(className, QLatin1String("QToolBox")) + || customWidgetsInfo()->extends(className, QLatin1String("QTabWidget")) + || customWidgetsInfo()->extends(className, QLatin1String("QScrollArea")) + || customWidgetsInfo()->extends(className, QLatin1String("QMdiArea")) + || customWidgetsInfo()->extends(className, QLatin1String("QWizard")) + || customWidgetsInfo()->extends(className, QLatin1String("QDockWidget")); +} + +bool Uic::isStatusBar(const QString &className) const +{ + return customWidgetsInfo()->extends(className, QLatin1String("QStatusBar")); +} + +bool Uic::isMenuBar(const QString &className) const +{ + return customWidgetsInfo()->extends(className, QLatin1String("QMenuBar")); +} + +bool Uic::isMenu(const QString &className) const +{ + return customWidgetsInfo()->extends(className, QLatin1String("QMenu")) + || customWidgetsInfo()->extends(className, QLatin1String("QPopupMenu")); +} + +QT_END_NAMESPACE diff --git a/src/tools/uic3/uic.h b/src/tools/uic3/uic.h new file mode 100644 index 0000000..33b897c --- /dev/null +++ b/src/tools/uic3/uic.h @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef UIC_H +#define UIC_H + +#include "databaseinfo.h" +#include "customwidgetsinfo.h" +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QHash> +#include <QtCore/QStack> + +QT_BEGIN_NAMESPACE + +class QTextStream; +class QIODevice; + +class Driver; +class DomUI; +class DomWidget; +class DomSpacer; +class DomLayout; +class DomLayoutItem; +class DomItem; + +struct Option; + +class Uic +{ +public: + Uic(Driver *driver); + ~Uic(); + + bool printDependencies(); + + inline Driver *driver() const + { return drv; } + + inline QTextStream &output() + { return out; } + + inline const Option &option() const + { return opt; } + + inline QString pixmapFunction() const + { return pixFunction; } + + inline void setPixmapFunction(const QString &f) + { pixFunction = f; } + + inline bool hasExternalPixmap() const + { return externalPix; } + + inline void setExternalPixmap(bool b) + { externalPix = b; } + + inline const DatabaseInfo *databaseInfo() const + { return &info; } + + inline const CustomWidgetsInfo *customWidgetsInfo() const + { return &cWidgetsInfo; } + + bool write(QIODevice *in); + +#ifdef QT_UIC_JAVA_GENERATOR + bool jwrite(DomUI *ui); +#endif + +#ifdef QT_UIC_CPP_GENERATOR + bool write(DomUI *ui); +#endif + + bool isMainWindow(const QString &className) const; + bool isToolBar(const QString &className) const; + bool isStatusBar(const QString &className) const; + bool isButton(const QString &className) const; + bool isContainer(const QString &className) const; + bool isMenuBar(const QString &className) const; + bool isMenu(const QString &className) const; + +private: + // copyright header + void writeCopyrightHeader(DomUI *ui); + +#ifdef QT_UIC_CPP_GENERATOR + // header protection + void writeHeaderProtectionStart(); + void writeHeaderProtectionEnd(); +#endif + +private: + Driver *drv; + QTextStream &out; + Option &opt; + DatabaseInfo info; + CustomWidgetsInfo cWidgetsInfo; + QString pixFunction; + bool externalPix; +}; + +QT_END_NAMESPACE + +#endif // UIC_H diff --git a/src/tools/uic3/uic3.pro b/src/tools/uic3/uic3.pro new file mode 100644 index 0000000..5ad3c4d --- /dev/null +++ b/src/tools/uic3/uic3.pro @@ -0,0 +1,43 @@ +TEMPLATE = app +CONFIG += console qt_no_compat_warning +CONFIG -= app_bundle +build_all:!build_pass { + CONFIG -= build_all + CONFIG += release +} + +QT += xml qt3support + +DESTDIR = ../../../bin + +include(../uic/uic.pri) +include(../uic/cpp/cpp.pri) + +INCLUDEPATH += . + +HEADERS += ui3reader.h \ + parser.h \ + domtool.h \ + widgetinfo.h \ + qt3to4.h \ + uic.h + +SOURCES += main.cpp \ + ui3reader.cpp \ + parser.cpp \ + domtool.cpp \ + object.cpp \ + subclassing.cpp \ + form.cpp \ + converter.cpp \ + widgetinfo.cpp \ + embed.cpp \ + qt3to4.cpp \ + deps.cpp \ + uic.cpp + +DEFINES -= QT_COMPAT_WARNINGS +DEFINES += QT_COMPAT QT_UIC3 + +target.path=$$[QT_INSTALL_BINS] +INSTALLS += target diff --git a/src/tools/uic3/widgetinfo.cpp b/src/tools/uic3/widgetinfo.cpp new file mode 100644 index 0000000..355b3bd --- /dev/null +++ b/src/tools/uic3/widgetinfo.cpp @@ -0,0 +1,285 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "widgetinfo.h" + +#include <QMetaEnum> +#include <QTextBrowser> +#include <QToolBar> +#include <QPushButton> +#include <QLineEdit> +#include <QComboBox> +#include <QDial> +#include <QSlider> +#include <QLCDNumber> +#include <QProgressBar> +#include <QLabel> +#include <QToolBox> +#include <QMainWindow> +#include <QToolButton> +#include <QCheckBox> +#include <QRadioButton> +#include <QSpinBox> +#include <QActionGroup> +#include <QSplitter> +#include <Q3Frame> +#include <QTabWidget> +#include <Q3DateEdit> +#include <Q3TimeEdit> +#include <Q3DateTimeEdit> +#include <Q3ListBox> +#include <Q3ListView> +#include <Q3TextEdit> +#include <Q3WidgetStack> +#include <Q3Wizard> +#include <Q3TextView> +#include <Q3MainWindow> +#include <Q3GroupBox> +#include <Q3ButtonGroup> +#include <Q3IconView> +#include <Q3ProgressBar> + +QT_BEGIN_NAMESPACE + +WidgetInfo::WidgetInfo() +{ +} + +const QMetaObject *WidgetInfo::metaObject(const QString &widgetName) +{ + if (widgetName == QLatin1String("QObject")) + return &QObject::staticMetaObject; + else if (widgetName == QLatin1String("QToolBar")) + return &QToolBar::staticMetaObject; + else if (widgetName == QLatin1String("Q3ToolBar")) + return &Q3ToolBar::staticMetaObject; + else if (widgetName == QLatin1String("QPushButton")) + return &QPushButton::staticMetaObject; + else if (widgetName == QLatin1String("QToolButton")) + return &QToolButton::staticMetaObject; + else if (widgetName == QLatin1String("QCheckBox")) + return &QCheckBox::staticMetaObject; + else if (widgetName == QLatin1String("QRadioButton")) + return &QRadioButton::staticMetaObject; + else if (widgetName == QLatin1String("QGroupBox") + || widgetName == QLatin1String("Q3GroupBox")) + return &Q3GroupBox::staticMetaObject; + else if (widgetName == QLatin1String("QButtonGroup") + || widgetName == QLatin1String("Q3ButtonGroup")) + return &Q3ButtonGroup::staticMetaObject; + else if (widgetName == QLatin1String("QDateEdit")) + return &Q3DateEdit::staticMetaObject; + else if (widgetName == QLatin1String("QTimeEdit")) + return &Q3TimeEdit::staticMetaObject; + else if (widgetName == QLatin1String("QDateTimeEdit")) + return &Q3DateTimeEdit::staticMetaObject; + else if (widgetName == QLatin1String("QListBox") + || widgetName == QLatin1String("Q3ListBox")) + return &Q3ListBox::staticMetaObject; + else if (widgetName == QLatin1String("QListView") || + widgetName == QLatin1String("Q3ListView")) + return &Q3ListView::staticMetaObject; + else if (widgetName == QLatin1String("Q3IconView")) + return &Q3IconView::staticMetaObject; + else if (widgetName == QLatin1String("QLineEdit")) + return &QLineEdit::staticMetaObject; + else if (widgetName == QLatin1String("QSpinBox")) + return &QSpinBox::staticMetaObject; + else if (widgetName == QLatin1String("QSplitter")) + return &QSplitter::staticMetaObject; + else if (widgetName == QLatin1String("QTextEdit") || + widgetName == QLatin1String("Q3TextEdit")) + return &Q3TextEdit::staticMetaObject; + else if (widgetName == QLatin1String("QLabel")) + return &QLabel::staticMetaObject; + else if (widgetName == QLatin1String("QTabWidget")) + return &QTabWidget::staticMetaObject; + else if (widgetName == QLatin1String("QWidgetStack")) + return &Q3WidgetStack::staticMetaObject; + else if (widgetName == QLatin1String("QComboBox")) + return &QComboBox::staticMetaObject; + else if (widgetName == QLatin1String("QWidget")) + return &QWidget::staticMetaObject; + else if (widgetName == QLatin1String("QDialog")) + return &QDialog::staticMetaObject; + else if (widgetName == QLatin1String("QWizard") || + widgetName == QLatin1String("Q3Wizard")) + return &Q3Wizard::staticMetaObject; + else if (widgetName == QLatin1String("QLCDNumber")) + return &QLCDNumber::staticMetaObject; + else if (widgetName == QLatin1String("QProgressBar")) + return &QProgressBar::staticMetaObject; + else if (widgetName == QLatin1String("Q3ProgressBar")) + return &Q3ProgressBar::staticMetaObject; + else if (widgetName == QLatin1String("QTextView") + || widgetName == QLatin1String("Q3TextView")) + return &Q3TextView::staticMetaObject; + else if (widgetName == QLatin1String("QTextBrowser")) + return &QTextBrowser::staticMetaObject; + else if (widgetName == QLatin1String("QDial")) + return &QDial::staticMetaObject; + else if (widgetName == QLatin1String("QSlider")) + return &QSlider::staticMetaObject; + else if (widgetName == QLatin1String("QScrollBar")) + return &QScrollBar::staticMetaObject; + else if (widgetName == QLatin1String("QFrame")) + return &QFrame::staticMetaObject; + else if (widgetName == QLatin1String("Q3Frame")) + return &Q3Frame::staticMetaObject; + else if (widgetName == QLatin1String("QMainWindow")) + return &QMainWindow::staticMetaObject; + else if (widgetName == QLatin1String("Q3MainWindow")) + return &Q3MainWindow::staticMetaObject; + else if (widgetName == QLatin1String("QToolBox")) + return &QToolBox::staticMetaObject; + else if (widgetName == QLatin1String("Line")) + return &QFrame::staticMetaObject; + else if (widgetName == QLatin1String("TextLabel")) + return &QLabel::staticMetaObject; + else if (widgetName == QLatin1String("PixmapLabel")) + return &QLabel::staticMetaObject; + else if (widgetName == QLatin1String("QActionGroup")) + return &QActionGroup::staticMetaObject; + else if (widgetName == QLatin1String("QAction")) + return &QAction::staticMetaObject; + + return 0; +} + +bool WidgetInfo::isValidProperty(const QString &className, const QString &name) +{ + const QMetaObject *meta = metaObject(className); + if (!meta) + return true; + + return meta->indexOfProperty(name.toLatin1()) != -1; +} + +bool WidgetInfo::isValidSignal(const QString &className, const QString &name) +{ + const QMetaObject *meta = metaObject(className); + if (!meta) + return true; + + return meta->indexOfSignal(name.toLatin1()) != -1; +} + +bool WidgetInfo::isValidSlot(const QString &className, const QString &name) +{ + const QMetaObject *meta = metaObject(className); + if (!meta) + return true; + + return meta->indexOfSlot(name.toLatin1()) != -1; +} + +bool WidgetInfo::isValidEnumerator(const QString &className, const QString &name) +{ + const QMetaObject *meta = metaObject(className); + if (!meta) + return true; + + return checkEnumerator(meta, name); +} + +bool WidgetInfo::checkEnumerator(const QMetaObject *meta, const QString &name) +{ + for (int i=0; i<meta->enumeratorCount(); ++i) + if (checkEnumerator(meta->enumerator(i), name)) + return true; + return false; +} + +bool WidgetInfo::checkEnumerator(const QMetaEnum &metaEnum, const QString &name) +{ + return metaEnum.keyToValue(name.toLatin1()) != -1; +} + + +QString WidgetInfo::resolveEnumerator(const QString &className, const QString &name) +{ + const QMetaObject *meta = metaObject(className); + if (!meta) { + QString e = resolveEnumerator(QLatin1String("QObject"), QLatin1String("Qt::") + name); + if (e.size()) + return e; + + return name; + } + + return resolveEnumerator(meta, name); +} + +QString WidgetInfo::resolveEnumerator(const QMetaObject *meta, const QString &name) +{ + for (int i=meta->enumeratorCount() - 1; i>=0; --i) { + QString e = resolveEnumerator(meta->enumerator(i), name); + if (e.size()) + return e; + } + + if (meta != &staticQtMetaObject) + return resolveEnumerator(&staticQtMetaObject, name); + + return QString(); +} + +QString WidgetInfo::resolveEnumerator(const QMetaEnum &metaEnum, const QString &name) +{ + QString scope = QLatin1String(metaEnum.scope()); + + QString enumerator = name; + int i = enumerator.indexOf(QLatin1String("::")); + if (i != -1) { + if (scope != enumerator.left(i)) + return QString(); + enumerator = enumerator.mid(i + 2); + } + QByteArray key = enumerator.toLatin1(); + for (int idx = 0; idx < metaEnum.keyCount(); ++idx) { + if (metaEnum.key(idx) == key) + return scope + QLatin1String("::") + enumerator; + } + + return QString(); +} + +QT_END_NAMESPACE diff --git a/src/tools/uic3/widgetinfo.h b/src/tools/uic3/widgetinfo.h new file mode 100644 index 0000000..98b01d8 --- /dev/null +++ b/src/tools/uic3/widgetinfo.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WIDGETINFO_H +#define WIDGETINFO_H + +#include <QObject> + +QT_BEGIN_NAMESPACE + +class QString; +struct QMetaObject; +class QMetaEnum; + +class WidgetInfo: public QObject +{ +protected: + WidgetInfo(); + +public: + static bool isValidProperty(const QString &className, const QString &name); + static bool isValidEnumerator(const QString &className, const QString &name); + static bool isValidSignal(const QString &className, const QString &name); + static bool isValidSlot(const QString &className, const QString &name); + + static QString resolveEnumerator(const QString &className, const QString &name); + +private: + static const QMetaObject *metaObject(const QString &widgetName); + static bool checkEnumerator(const QMetaObject *meta, const QString &name); + static bool checkEnumerator(const QMetaEnum &metaEnum, const QString &name); + + static QString resolveEnumerator(const QMetaObject *meta, const QString &name); + static QString resolveEnumerator(const QMetaEnum &metaEnum, const QString &name); +}; + +QT_END_NAMESPACE + +#endif // WIDGETINFO_H |