/**************************************************************************** ** ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.1, 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 have questions regarding the use of this file, please contact ** Nokia at qt-info@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 #include #include #include #include #include #include #include #include #include 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 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) { 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 ui_includes; QList ui_toolbars; QList ui_menubars; QList ui_action_list; QList ui_action_group_list; QList ui_customwidget_list; QList ui_connection_list; QList > 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 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 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 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(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 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 (const 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 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; ielementClass(); if (candidateCustomWidgets.contains(name)) candidateCustomWidgets.remove(name); } QMapIterator 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 ((m_options & 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.limitXPM_LineLength = (m_options & LimitXPM_LineLength) ? 1 : 0; 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 inclList = res->elementInclude(); inclList.append(incl); res->setElementInclude(inclList); if (!ui->elementResources()) ui->setElementResources(res); } return ui; } QString Ui3Reader::fixActionProperties(QList &properties, bool isActionGroup) { QString objectName; QMutableListIterator 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 groups = g->elementActionGroup(); for (int i=0; i actions = g->elementAction(); for (int i=0; i properties = a->elementProperty(); QString name = fixActionProperties(properties); a->setElementProperty(properties); if (name.size()) a->setAttributeName(name); } QList 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 ui_child_list; QList ui_row_list; QList ui_column_list; QList ui_item_list; QList ui_property_list; QList ui_attribute_list; QList ui_layout_list; QList ui_action_list; QList 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 const QString name = e.attribute(QLatin1String("name")); // change the varname this widget if (name == QLatin1String("name")) { // Do not name QLayoutWidget if layout names are to be used. const bool applyName = !(m_options & PreserveLayoutNames) || className != QLatin1String("QLayoutWidget"); if (applyName) 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 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 ui_item_list; QList ui_property_list; QList 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); if (m_options & PreserveLayoutNames) { const QString layoutName = getLayoutName(w); if (!layoutName.isEmpty()) lay->setAttributeName(layoutName); } 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 layouts = ui_widget->elementLayout(); ui_widget->setElementLayout(QList()); 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 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 *properties, const QString &className) { QString objectName; bool wordWrapFound = false; bool wordWrapPropertyFound = 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")) { if (name == QLatin1String("alignment")) { const QString v = prop->elementSet(); if (v.contains(QRegExp(QLatin1String("\\bWordBreak\\b")))) wordWrapFound = true; } else if (name == QLatin1String("wordWrap")) { wordWrapPropertyFound = true; } } // resolve the flags and enumerator if (prop->kind() == DomProperty::Set) { QStringList flags = prop->elementSet().split(QLatin1Char('|')); QStringList v; foreach (const 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") && !wordWrapPropertyFound) { 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 *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(const 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