blob: 56aff8545e294ac5829b5e9babf37eadbfb51ec0 [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2011 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$
** GNU Lesser General Public License Usage
** 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $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)
{
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 (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<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 ((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<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
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<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);
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<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;
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<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(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