Mercurial > projects > qtd
view generator/uiconverter.cpp @ 159:7ae51fb20f61
core: add QVariant.type()
author | SokoL_SD |
---|---|
date | Wed, 17 Jun 2009 15:34:57 +0000 |
parents | e78566595089 |
children |
line wrap: on
line source
/**************************************************************************** ** ** Copyright (C) 1992-2008 Nokia. All rights reserved. ** ** This file is part of Qt Jambi. ** ** * 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 General Public License Usage * Alternatively, this file may be used under the terms of the GNU * General Public License versions 2.0 or 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 GNU General Public Licensing requirements will be met: * http://www.fsf.org/licensing/licenses/info/GPLv2.html and * http://www.gnu.org/copyleft/gpl.html. In addition, as a special * exception, Nokia gives you certain additional rights. These rights * are described in the Nokia Qt GPL Exception version 1.2, included in * the file GPL_EXCEPTION.txt in this package. * * Qt for Windows(R) Licensees * As a special exception, Nokia, as the sole copyright holder for Qt * Designer, grants users of the Qt/Eclipse Integration plug-in the * right for the Qt/Eclipse Integration to link to functionality * provided by Qt Designer and its related libraries. * * * If you are unsure which license is appropriate for your use, please * contact the sales department at qt-sales@nokia.com. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ #include "uiconverter.h" #include "metajava.h" #include "reporthandler.h" #include <QtCore/QFileInfo> #include <QtXml/QDomDocument> void UiConverter::convertToJui(const QString &uiFile, const QString &customWidgetFiles) { ReportHandler::setContext(QLatin1String("UiConverter to .jui")); traverseCustomWidgets(customWidgetFiles); QFileInfo fileInfo(uiFile); if (!fileInfo.exists()) { ReportHandler::warning(QString::fromLatin1("Ui File %1 doesn't exist...\n").arg(uiFile)); return; } if (fileInfo.suffix() != QLatin1String("ui")) { ReportHandler::warning(QString::fromLatin1("File doesn't have .ui extension: %1") .arg(uiFile)); return; } QString juiFile = fileInfo.absolutePath() + QLatin1Char('/') + fileInfo.baseName() + QLatin1String(".jui"); QFile inputFile(uiFile); if (!inputFile.open(QFile::ReadOnly | QFile::Text)) { ReportHandler::warning(QString::fromLatin1("Could not open '%1' for reading").arg(uiFile)); return; } QDomDocument dom; QString error; if (!dom.setContent(&inputFile, false, &error)) { ReportHandler::warning(QString::fromLatin1("Xml loading %1 failed: %2") .arg(uiFile).arg(error)); inputFile.close(); return; } inputFile.close(); QDomNodeList customWidgets = dom.documentElement().elementsByTagName("customwidget"); for (int i=0; i<customWidgets.size(); ++i) { QDomNode customWidget = customWidgets.at(i); QDomElement el = customWidget.toElement(); fixCustomWidgetNode(el, &dom); } traverse(dom.documentElement(), &dom); QFile outputFile(juiFile); if (!outputFile.open(QFile::WriteOnly | QFile::Text)) { ReportHandler::warning(QString::fromLatin1("Could not open '%1' for writing") .arg(juiFile)); return; } outputFile.write(dom.toByteArray()); outputFile.close(); } void UiConverter::traverseCustomWidgetFile(const QString &customWidgetFile) { if (customWidgetFile.isEmpty()) return; QFile file(customWidgetFile); if (!file.open(QIODevice::ReadOnly)) { ReportHandler::warning("Can't read custom widget file '" + customWidgetFile + "'"); return; } QXmlStreamReader reader(&file); while (!reader.atEnd()) { reader.readNext(); if (reader.isStartElement() && reader.name() == "qt-jambi-custom-widget") { QXmlStreamAttributes attributes = reader.attributes(); QString className = attributes.value("class").toString(); int pos = className.lastIndexOf("."); m_custom_widgets.insertMulti(className.mid(pos+1), CustomWidget(className, 0)); } } if (reader.hasError()) { ReportHandler::warning("Error when parsing custom widget file '" + customWidgetFile + "': " + reader.errorString()); } } void UiConverter::traverseCustomWidgets(const QString &customWidgetFiles) { #ifdef Q_OS_WIN32 char separator = ';'; #else char separator = ':'; #endif QStringList customWidgets = customWidgetFiles.split(separator); foreach (QString customWidget, customWidgets) traverseCustomWidgetFile(customWidget); } void UiConverter::traverse(QDomNode node, QDomDocument *doc) { if (node.isNull()) return; QDomElement element = node.toElement(); if (!element.isNull()) { if (element.nodeName() == QLatin1String("ui")) fixUiNode(element, doc); else if (element.nodeName() == QLatin1String("set")) fixSetNode(element, doc); else if (element.nodeName() == QLatin1String("enum")) fixEnumNode(element, doc); else if (element.nodeName() == QLatin1String("connection")) fixConnectionNode(element, doc); else if (element.nodeName() == QLatin1String("widget")) fixWidgetNode(element, doc); } QDomNodeList list = node.childNodes(); for (int i=0; i<list.size(); ++i) traverse(list.at(i), doc); } void UiConverter::fixUiNode(QDomElement el, QDomDocument *) { el.setAttribute("language", "jambi"); } void UiConverter::fixCustomWidgetNode(QDomElement el, QDomDocument *) { QDomNodeList classes = el.elementsByTagName("class"); if (classes.size() < 1) { ReportHandler::warning("Custom widget missing 'class' child"); return; } QDomNodeList extendss = el.elementsByTagName("extends"); if (extendss.size() < 1) { ReportHandler::warning("Custom widget missing 'extends' child"); return; } QString className = classes.at(0).toElement().text(); QString extends = extendss.at(0).toElement().text(); AbstractMetaClass *javaClass = m_java_classes.findClass(extends); if (javaClass == 0) { ReportHandler::warning("Couldn't find super class for custom widget: '" + extends + "'"); return; } QList<CustomWidget> fullNames = m_custom_widgets.values(className); if (fullNames.size() == 0) { ReportHandler::warning("Couldn't find custom widget entry for '" + className + "'." " You need to specify this class in a custom widget file and" " pass the file name on the command line using the --custom-widgets option."); return; } if (fullNames.size() > 1) { ReportHandler::warning("More than custom widget type matching '" + className + "'. " + "Will use first seen entry: '" + fullNames.at(0).first + "'"); } QString fullName = fullNames.at(0).first; classes.at(0).namedItem("#text").toText().setData(fullName); QMap<QString, CustomWidget>::iterator it; for (it=m_custom_widgets.begin(); it!=m_custom_widgets.end(); ++it) { if (it.key() == className) (*it).second = javaClass; } } void UiConverter::fixSetNode(QDomElement el, QDomDocument *) { QStringList cppSet = el.firstChild().nodeValue().split(QLatin1Char('|')); QStringList javaSet; for (int i=0; i<cppSet.size(); ++i) javaSet << translateEnumValue(cppSet.at(i)); el.firstChild().setNodeValue(javaSet.join(QLatin1String("|"))); } void UiConverter::fixEnumNode(QDomElement el, QDomDocument *) { QDomNode valueNode = el.firstChild(); if (valueNode.isNull()) { ReportHandler::warning(QString::fromLatin1("Bad enum value at '%1'").arg(el.nodeValue())); return; } QString cppEnumValue = valueNode.nodeValue(); QString javaEnumValue = translateEnumValue(cppEnumValue); valueNode.setNodeValue(javaEnumValue); } void UiConverter::fixConnectionNode(QDomElement el, QDomDocument *) { QString senderName = el.namedItem("sender").firstChild().nodeValue(); AbstractMetaClass *senderClass = m_named_widgets[senderName]; if (!senderClass) { ReportHandler::warning(QString::fromLatin1("sender unknown '%1'").arg(senderName)); return; } QDomNode signalSignatureNode = el.namedItem("signal").toElement().firstChild(); QString signalSignature = signalSignatureNode.nodeValue(); const AbstractMetaFunction *signalFunction = findFunction(senderClass, signalSignature, SignalSearch); if (!signalFunction) { ReportHandler::warning(QString::fromLatin1("Signal not found '%1' in '%2'") .arg(signalSignature).arg(senderClass->qualifiedCppName())); return; } signalSignatureNode.setNodeValue(signalFunction->modifiedName()); QString receiverName = el.namedItem("receiver").firstChild().nodeValue(); AbstractMetaClass *receiverClass = m_named_widgets[receiverName]; if (!receiverClass) { ReportHandler::warning(QString::fromLatin1("receiver unknown '%1'").arg(receiverName)); return; } QDomNode slotSignatureNode = el.namedItem("slot").firstChild(); QString slotSignature = slotSignatureNode.nodeValue(); const AbstractMetaFunction *slotFunction = findFunction(receiverClass, slotSignature, SlotSearch); if (!signalFunction) { ReportHandler::warning(QString::fromLatin1("Slot not found '%1' in '%2'") .arg(slotSignature).arg(receiverClass->qualifiedCppName())); return; } slotSignatureNode.setNodeValue(slotFunction->targetLangSignature(true)); } void UiConverter::fixWidgetNode(QDomElement el, QDomDocument *) { QString className = el.attribute(QLatin1String("class")); QList<CustomWidget> customWidgetNames = m_custom_widgets.values(className); QString customWidgetName = customWidgetNames.size() > 0 ? customWidgetNames.at(0).first : QString(); AbstractMetaClass *javaClass = customWidgetName.isEmpty() ? m_java_classes.findClass(className) : customWidgetNames.at(0).second; if (!javaClass) { ReportHandler::warning(QString::fromLatin1("Class '%1' is unknown").arg(className)); return; } if (!customWidgetName.isEmpty()) el.setAttribute(QLatin1String("class"), customWidgetName); else if (javaClass->package() != QLatin1String("qt.gui")) el.setAttribute(QLatin1String("class"), javaClass->fullName()); m_named_widgets.insert(el.attribute(QLatin1String("name")), javaClass); } QString UiConverter::translateEnumValue(const QString &cppEnumValue) { if (!cppEnumValue.contains(QLatin1String("::"))) { ReportHandler::warning(QString::fromLatin1("Expected '::' in enum value '%1'") .arg(cppEnumValue)); return QString(); } QStringList names = cppEnumValue.split(QLatin1String("::")); AbstractMetaClass *javaClass = m_java_classes.findClass(names.at(0)); if (!javaClass) { ReportHandler::warning(QString::fromLatin1("Class '%1' is unknown").arg(names.at(0))); return QString(); } AbstractMetaEnum *javaEnum = javaClass->findEnumForValue(names.at(1)); if (!javaEnum) { ReportHandler::warning(QString::fromLatin1("Enum value '%1' was not found in '%2'") .arg(names.at(1)).arg(names.at(0))); return QString(); } AbstractMetaEnumValueList enumValues = javaEnum->values(); AbstractMetaEnumValue *enumValue = enumValues.find(names.at(1)); int value = enumValue->value(); if (javaEnum->typeEntry()->isEnumValueRejected(enumValue->name())) { for (int i=0; i<enumValues.size(); ++i) { AbstractMetaEnumValue *ev = enumValues.at(i); if (ev->value() == value) { enumValue = ev; break; } } } return javaEnum->fullName() + QLatin1String(".") + enumValue->name(); } const AbstractMetaFunction *UiConverter::findFunction(AbstractMetaClass *javaClass, const QString &signature, SearchType type) { AbstractMetaFunctionList senderFunctions = javaClass->functions(); foreach (const AbstractMetaFunction *f, senderFunctions) { if (type == SignalSearch && !f->isSignal()) continue; QString fsig = f->minimalSignature(); int pos = 0; while (pos < signature.length() && fsig.constData()[pos] == signature.constData()[pos]) ++pos; if (pos == signature.length() || (type == SignalSearch && pos == signature.length() - 1 && signature.constData()[pos] == QLatin1Char(')'))) { return f; } } return 0; }