Mercurial > projects > qtd
diff tools/duic/d/dwriteincludes.cpp @ 1:e78566595089
initial import
author | mandel |
---|---|
date | Mon, 11 May 2009 16:01:50 +0000 |
parents | |
children | 2085c2157b50 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/duic/d/dwriteincludes.cpp Mon May 11 16:01:50 2009 +0000 @@ -0,0 +1,316 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** 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.3, 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. +** +****************************************************************************/ + +#include "dwriteincludes.h" +#include "driver.h" +#include "ui4.h" +#include "uic.h" +#include "databaseinfo.h" +#include <QtCore/QDebug> +#include <QtCore/QFileInfo> +#include <QtCore/QTextStream> + +QT_BEGIN_NAMESPACE + +namespace { + enum { debugWriteIncludes = 0 }; + enum { warnHeaderGeneration = 0 }; +} + +namespace D { + +struct ClassInfoEntry +{ + const char *klass; + const char *module; + const char *header; +}; + +static const ClassInfoEntry qclass_lib_map[] = { +#define QT_CLASS_LIB(klass, module, header) { #klass, #module, #header }, +#include "qclass_lib_map.h" + +#undef QT_CLASS_LIB + { 0, 0, 0 } +}; + +WriteIncludes::WriteIncludes(Uic *uic) : + m_uic(uic), + m_output(uic->output()), + m_scriptsActivated(false) +{ + for(const ClassInfoEntry *it = &qclass_lib_map[0]; it->klass != 0; ++it) { + QString newHeader = QString("qt.%1").arg(QString(it->module).mid(2).toLower()); + newHeader += QLatin1Char('.'); + newHeader += QLatin1String(it->klass); + m_classToHeader.insert(QLatin1String(it->klass), newHeader); + m_oldHeaderToNewHeader.insert(QLatin1String(it->header), newHeader); + } +} + +void WriteIncludes::acceptUI(DomUI *node) +{ + m_scriptsActivated = false; + m_localIncludes.clear(); + m_globalIncludes.clear(); + m_knownClasses.clear(); + m_includeBaseNames.clear(); + + if (node->elementIncludes()) + acceptIncludes(node->elementIncludes()); + + if (node->elementCustomWidgets()) + TreeWalker::acceptCustomWidgets(node->elementCustomWidgets()); + + add(QLatin1String("QApplication")); + add(QLatin1String("QVariant")); + add(QLatin1String("QAction")); + + add(QLatin1String("QButtonGroup")); // ### only if it is really necessary + + if (m_uic->hasExternalPixmap() && m_uic->pixmapFunction() == QLatin1String("qPixmapFromMimeSource")) { +#ifdef QT_NO_QT3_SUPPORT + qWarning("Warning: The form file has external pixmaps or qPixmapFromMimeSource() set as a pixmap function. " + "This requires Qt 3 support, which is disabled. The resulting code will not compile."); +#endif + add(QLatin1String("qt.qt3support.Q3MimeSourceFactory")); + } + + if (m_uic->databaseInfo()->connections().size()) { + add(QLatin1String("QSqlDatabase")); + add(QLatin1String("Q3SqlCursor")); + add(QLatin1String("QSqlRecord")); + add(QLatin1String("Q3SqlForm")); + } + + TreeWalker::acceptUI(node); + + QString qualifiedClassName = node->elementClass(); + m_output << "module ui." << qualifiedClassName << "\n\n"; + + writeHeaders(m_globalIncludes, true); + writeHeaders(m_localIncludes, false); + + m_output << QLatin1Char('\n'); +} + +void WriteIncludes::acceptWidget(DomWidget *node) +{ + add(QString("%1").arg(node->attributeClass())); + TreeWalker::acceptWidget(node); +} + +void WriteIncludes::acceptLayout(DomLayout *node) +{ + add(QString("%1").arg(node->attributeClass())); + TreeWalker::acceptLayout(node); +} + +void WriteIncludes::acceptSpacer(DomSpacer *node) +{ + add(QLatin1String("QSpacerItem")); + TreeWalker::acceptSpacer(node); +} + +void WriteIncludes::acceptProperty(DomProperty *node) +{ + if (node->kind() == DomProperty::Date) + add(QLatin1String("QDate")); + if (node->kind() == DomProperty::Locale) + add(QLatin1String("QLocale")); + TreeWalker::acceptProperty(node); +} + +void WriteIncludes::insertIncludeForClass(const QString &className, QString header, bool global) +{ + if (debugWriteIncludes) + qDebug() << "WriteIncludes::insertIncludeForClass" << className << header << global; + + do { + if (!header.isEmpty()) + break; + + // Known class + const StringMap::const_iterator it = m_classToHeader.constFind(className); + if (it != m_classToHeader.constEnd()) { + header = it.value(); + global = true; + break; + } + + // Quick check by class name to detect includehints provided for custom widgets. + // Remove namespaces + QString lowerClassName = className; + static const QString namespaceSeparator = QLatin1String("."); + const int namespaceIndex = lowerClassName.lastIndexOf(namespaceSeparator); + if (namespaceIndex != -1) + lowerClassName.remove(0, namespaceIndex + namespaceSeparator.size()); + if (m_includeBaseNames.contains(lowerClassName)) { + header.clear(); + break; + } + + // Last resort: Create default header + if (!m_uic->option().implicitIncludes) + break; + header = lowerClassName; + header += QLatin1String(""); + if (warnHeaderGeneration) { + qWarning("Warning: generated header '%s' for class '%s'.", qPrintable(header), + qPrintable(className)); + + } + + global = true; + } while (false); + + if (!header.isEmpty()) + insertInclude(header, global); +} + +void WriteIncludes::add(const QString &className, bool determineHeader, const QString &header, bool global) +{ + if (debugWriteIncludes) + qDebug() << "WriteIncludes::add" << className << header << global; + + if (className.isEmpty() || m_knownClasses.contains(className)) + return; + + m_knownClasses.insert(className); + + if (className == QLatin1String("Line")) { // ### hmm, deprecate me! + add(QLatin1String("qt.gui.QFrame")); + return; + } + + if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3ListView")) || + m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3Table"))) { + add(QLatin1String("qt.qt3support.Q3Header")); + } + if (determineHeader) + insertIncludeForClass(className, header, global); +} + +void WriteIncludes::acceptCustomWidget(DomCustomWidget *node) +{ + const QString className = node->elementClass(); + if (className.isEmpty()) + return; + + if (const DomScript *domScript = node->elementScript()) + if (!domScript->text().isEmpty()) + activateScripts(); + + if (!node->elementHeader() || node->elementHeader()->text().isEmpty()) { + add(className, false); // no header specified + } else { + // custom header unless it is a built-in qt class + QString header; + bool global = false; + if (!m_classToHeader.contains(className)) { + global = node->elementHeader()->attributeLocation().toLower() == QLatin1String("global"); + header = node->elementHeader()->text(); + } + add(className, true, header, global); + } +} + +void WriteIncludes::acceptCustomWidgets(DomCustomWidgets *node) +{ + Q_UNUSED(node); +} + +void WriteIncludes::acceptIncludes(DomIncludes *node) +{ + TreeWalker::acceptIncludes(node); +} + +void WriteIncludes::acceptInclude(DomInclude *node) +{ + bool global = true; + if (node->hasAttributeLocation()) + global = node->attributeLocation() == QLatin1String("global"); + insertInclude(node->text(), global); +} +void WriteIncludes::insertInclude(const QString &header, bool global) +{ + if (debugWriteIncludes) + qDebug() << "WriteIncludes::insertInclude" << header << global; + + OrderedSet &includes = global ? m_globalIncludes : m_localIncludes; + if (includes.contains(header)) + return; + // Insert. Also remember base name for quick check of suspicious custom plugins + includes.insert(header, false); + const QString lowerBaseName = QFileInfo(header).completeBaseName ().toLower(); + m_includeBaseNames.insert(lowerBaseName); +} + +void WriteIncludes::writeHeaders(const OrderedSet &headers, bool global) +{ + const QChar openingQuote = global ? QLatin1Char('<') : QLatin1Char('"'); + const QChar closingQuote = global ? QLatin1Char('>') : QLatin1Char('"'); + + const OrderedSet::const_iterator cend = headers.constEnd(); + for ( OrderedSet::const_iterator sit = headers.constBegin(); sit != cend; ++sit) { + const StringMap::const_iterator hit = m_oldHeaderToNewHeader.constFind(sit.key()); + const bool mapped = hit != m_oldHeaderToNewHeader.constEnd(); + const QString header = mapped ? hit.value() : sit.key(); + if (!header.trimmed().isEmpty()) { + m_output << "import " << header << QLatin1Char(';') << QLatin1Char('\n'); + } + } +} + +void WriteIncludes::acceptWidgetScripts(const DomScripts &scripts, DomWidget *, const DomWidgets &) +{ + if (!scripts.empty()) { + activateScripts(); + } +} + +void WriteIncludes::activateScripts() +{ + if (!m_scriptsActivated) { + add(QLatin1String("qt.script.QScriptEngine")); + add(QLatin1String("qt.core.QDebug")); + m_scriptsActivated = true; + } +} +} // namespace D + +QT_END_NAMESPACE