blob: 2caad115855a1f4320a52e3deda786d004fc1ed9 [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 "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