uic: Add python
- Add command line option - Add import (include) handling - Add language helpers like streamable classes for Function definition, object instantiation - Implement header comment formatting Task-number: PYSIDE-797 Change-Id: I15041ab16504ea159f6665781a829cd548585af1 Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
This commit is contained in:
parent
89120c4a76
commit
bc8633036c
@ -40,6 +40,7 @@
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QTextStream;
|
||||
class CustomWidgetsInfo;
|
||||
class Driver;
|
||||
class Uic;
|
||||
|
||||
@ -74,6 +75,9 @@ struct WriteIncludes : public TreeWalker
|
||||
void acceptIncludes(DomIncludes *node) override;
|
||||
void acceptInclude(DomInclude *node) override;
|
||||
|
||||
protected:
|
||||
QTextStream &output() const { return m_output; }
|
||||
|
||||
private:
|
||||
void add(const QString &className, bool determineHeader = true, const QString &header = QString(), bool global = false);
|
||||
|
||||
|
@ -71,7 +71,7 @@ namespace {
|
||||
// Write a statement to create a spacer item.
|
||||
void writeSpacerItem(const DomSpacer *node, QTextStream &output) {
|
||||
const QHash<QString, DomProperty *> properties = propertyMap(node->elementProperty());
|
||||
output << "new QSpacerItem(";
|
||||
output << language::operatorNew << "QSpacerItem(";
|
||||
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
@ -495,8 +495,9 @@ void WriteInitialization::acceptUI(DomUI *node)
|
||||
|
||||
const QString widgetClassName = node->elementWidget()->attributeClass();
|
||||
|
||||
m_output << m_option.indent << "void " << "setupUi(" << widgetClassName << " *" << varName << ")\n"
|
||||
<< m_option.indent << "{\n";
|
||||
const QString parameterType = widgetClassName + QLatin1String(" *");
|
||||
m_output << m_option.indent
|
||||
<< language::startFunctionDefinition1("setupUi", parameterType, varName, m_option.indent);
|
||||
|
||||
const QStringList connections = m_uic->databaseInfo()->connections();
|
||||
for (int i=0; i<connections.size(); ++i) {
|
||||
@ -550,7 +551,7 @@ void WriteInitialization::acceptUI(DomUI *node)
|
||||
if (m_option.autoConnection)
|
||||
m_output << "\n" << m_indent << "QMetaObject::connectSlotsByName(" << varName << ");\n";
|
||||
|
||||
m_output << m_option.indent << "} // setupUi\n\n";
|
||||
m_output << m_option.indent << language::endFunctionDefinition("setupUi");
|
||||
|
||||
if (!m_mainFormUsedInRetranslateUi) {
|
||||
m_refreshInitialization += m_indent;
|
||||
@ -559,10 +560,10 @@ void WriteInitialization::acceptUI(DomUI *node)
|
||||
m_refreshInitialization += QLatin1String(");\n");
|
||||
}
|
||||
|
||||
m_output << m_option.indent << "void " << "retranslateUi(" << widgetClassName << " *" << varName << ")\n"
|
||||
<< m_option.indent << "{\n"
|
||||
m_output << m_option.indent
|
||||
<< language::startFunctionDefinition1("retranslateUi", parameterType, varName, m_option.indent)
|
||||
<< m_refreshInitialization
|
||||
<< m_option.indent << "} // retranslateUi\n\n";
|
||||
<< m_option.indent << language::endFunctionDefinition("retranslateUi");
|
||||
|
||||
m_layoutChain.pop();
|
||||
m_widgetChain.pop();
|
||||
@ -612,8 +613,9 @@ void WriteInitialization::acceptWidget(DomWidget *node)
|
||||
const auto *cwi = m_uic->customWidgetsInfo();
|
||||
|
||||
if (m_widgetChain.size() != 1) {
|
||||
m_output << m_indent << varName << " = new " << cwi->realClassName(className)
|
||||
<< '(' << parentWidget << ");\n";
|
||||
m_output << m_indent << varName << " = " << language::operatorNew
|
||||
<< language::fixClassName(cwi->realClassName(className))
|
||||
<< '(' << parentWidget << ')' << language::eol;
|
||||
}
|
||||
|
||||
parentWidget = savedParentWidget;
|
||||
@ -846,7 +848,8 @@ void WriteInitialization::addButtonGroup(const DomWidget *buttonNode, const QStr
|
||||
m_output << m_indent;
|
||||
if (createGroupOnTheFly)
|
||||
m_output << className << " *";
|
||||
m_output << groupName << " = new " << className << '(' << m_mainFormVarName << ");\n";
|
||||
m_output << groupName << " = " << language::operatorNew
|
||||
<< className << '(' << m_mainFormVarName << ')' << language::eol;
|
||||
m_buttonGroups.insert(groupName);
|
||||
writeProperties(groupName, className, group->elementProperty());
|
||||
}
|
||||
@ -863,7 +866,7 @@ void WriteInitialization::acceptLayout(DomLayout *node)
|
||||
|
||||
bool isGroupBox = false;
|
||||
|
||||
m_output << m_indent << varName << " = new " << className << '(';
|
||||
m_output << m_indent << varName << " = " << language::operatorNew << className << '(';
|
||||
|
||||
if (!m_layoutChain.top() && !isGroupBox)
|
||||
m_output << m_driver->findOrInsertWidget(m_widgetChain.top());
|
||||
@ -1037,7 +1040,8 @@ void WriteInitialization::acceptActionGroup(DomActionGroup *node)
|
||||
if (m_actionGroupChain.top())
|
||||
varName = m_driver->findOrInsertActionGroup(m_actionGroupChain.top());
|
||||
|
||||
m_output << m_indent << actionName << " = new QActionGroup(" << varName << ");\n";
|
||||
m_output << m_indent << actionName << " = " << language::operatorNew
|
||||
<< "QActionGroup(" << varName << ");\n";
|
||||
writeProperties(actionName, QLatin1String("QActionGroup"), node->elementProperty());
|
||||
|
||||
m_actionGroupChain.push(node);
|
||||
@ -1057,7 +1061,8 @@ void WriteInitialization::acceptAction(DomAction *node)
|
||||
if (m_actionGroupChain.top())
|
||||
varName = m_driver->findOrInsertActionGroup(m_actionGroupChain.top());
|
||||
|
||||
m_output << m_indent << actionName << " = new QAction(" << varName << ");\n";
|
||||
m_output << m_indent << actionName << " = " << language::operatorNew
|
||||
<< "QAction(" << varName << ')' << language::eol;
|
||||
writeProperties(actionName, QLatin1String("QAction"), node->elementProperty());
|
||||
}
|
||||
|
||||
@ -1322,8 +1327,8 @@ void WriteInitialization::writeProperties(const QString &varName,
|
||||
case DomProperty::Palette: {
|
||||
const DomPalette *pal = p->elementPalette();
|
||||
const QString paletteName = m_driver->unique(QLatin1String("palette"));
|
||||
m_output << m_indent << "QPalette " << paletteName << ";\n";
|
||||
|
||||
m_output << m_indent << language::stackVariable("QPalette", paletteName)
|
||||
<< language::eol;
|
||||
writeColorGroup(pal->elementActive(), QLatin1String("QPalette::Active"), paletteName);
|
||||
writeColorGroup(pal->elementInactive(), QLatin1String("QPalette::Inactive"), paletteName);
|
||||
writeColorGroup(pal->elementDisabled(), QLatin1String("QPalette::Disabled"), paletteName);
|
||||
@ -1512,20 +1517,15 @@ QString WriteInitialization::writeSizePolicy(const DomSizePolicy *sp)
|
||||
const QString spName = m_driver->unique(QLatin1String("sizePolicy"));
|
||||
m_sizePolicyNameMap.insert(sizePolicyHandle, spName);
|
||||
|
||||
m_output << m_indent << "QSizePolicy " << spName;
|
||||
do {
|
||||
m_output << m_indent << language::stackVariableWithInitParameters("QSizePolicy", spName);
|
||||
if (sp->hasElementHSizeType() && sp->hasElementVSizeType()) {
|
||||
m_output << "(QSizePolicy::" << language::sizePolicy(sp->elementHSizeType())
|
||||
<< ", QSizePolicy::" << language::sizePolicy(sp->elementVSizeType()) << ");\n";
|
||||
break;
|
||||
m_output << "QSizePolicy" << language::qualifier << language::sizePolicy(sp->elementHSizeType())
|
||||
<< ", QSizePolicy" << language::qualifier << language::sizePolicy(sp->elementVSizeType());
|
||||
} else if (sp->hasAttributeHSizeType() && sp->hasAttributeVSizeType()) {
|
||||
m_output << "QSizePolicy::" << sp->attributeHSizeType() << ", QSizePolicy::"
|
||||
<< sp->attributeVSizeType();
|
||||
}
|
||||
if (sp->hasAttributeHSizeType() && sp->hasAttributeVSizeType()) {
|
||||
m_output << "(QSizePolicy::" << sp->attributeHSizeType() << ", QSizePolicy::"
|
||||
<< sp->attributeVSizeType() << ");\n";
|
||||
break;
|
||||
}
|
||||
m_output << ";\n";
|
||||
} while (false);
|
||||
m_output << ')' << language::eol;
|
||||
|
||||
m_output << m_indent << spName << ".setHorizontalStretch("
|
||||
<< sp->elementHorStretch() << ");\n";
|
||||
@ -1549,7 +1549,8 @@ QString WriteInitialization::writeFontProperties(const DomFont *f)
|
||||
const QString fontName = m_driver->unique(QLatin1String("font"));
|
||||
m_fontPropertiesNameMap.insert(FontHandle(f), fontName);
|
||||
|
||||
m_output << m_indent << "QFont " << fontName << ";\n";
|
||||
m_output << m_indent << language::stackVariable("QFont", fontName)
|
||||
<< language::eol;
|
||||
if (f->hasElementFamily() && !f->elementFamily().isEmpty()) {
|
||||
m_output << m_indent << fontName << ".setFamily("
|
||||
<< language::qstring(f->elementFamily(), m_dindent) << ");\n";
|
||||
@ -2512,7 +2513,8 @@ QString WriteInitialization::Item::writeSetupUi(const QString &parent, Item::Emp
|
||||
bool generateMultiDirective = false;
|
||||
if (emptyItemPolicy == Item::ConstructItemOnly && m_children.isEmpty()) {
|
||||
if (m_setupUiData.policy == ItemData::DontGenerate) {
|
||||
m_setupUiStream << m_indent << "new " << m_itemClassName << '(' << parent << ");\n";
|
||||
m_setupUiStream << m_indent << language::operatorNew << m_itemClassName
|
||||
<< '(' << parent << ')' << language::eol;
|
||||
return QString();
|
||||
}
|
||||
if (m_setupUiData.policy == ItemData::GenerateWithMultiDirective)
|
||||
@ -2523,11 +2525,17 @@ QString WriteInitialization::Item::writeSetupUi(const QString &parent, Item::Emp
|
||||
generateMultiDirectiveBegin(m_setupUiStream, m_setupUiData.directives);
|
||||
|
||||
const QString uniqueName = m_driver->unique(QLatin1String("__") + m_itemClassName.toLower());
|
||||
m_setupUiStream << m_indent << m_itemClassName << " *" << uniqueName << " = new " << m_itemClassName << '(' << parent << ");\n";
|
||||
m_setupUiStream << m_indent;
|
||||
if (language::language() == Language::Cpp)
|
||||
m_setupUiStream << m_itemClassName << " *";
|
||||
m_setupUiStream << uniqueName
|
||||
<< " = " << language::operatorNew << m_itemClassName << '(' << parent
|
||||
<< ')' << language::eol;
|
||||
|
||||
if (generateMultiDirective) {
|
||||
m_setupUiStream << "#else\n";
|
||||
m_setupUiStream << m_indent << "new " << m_itemClassName << '(' << parent << ");\n";
|
||||
m_setupUiStream << m_indent << language::operatorNew << m_itemClassName
|
||||
<< '(' << parent << ')' << language::eol;
|
||||
generateMultiDirectiveEnd(m_setupUiStream, m_setupUiData.directives);
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "uic.h"
|
||||
#include "option.h"
|
||||
#include "driver.h"
|
||||
#include <language.h>
|
||||
|
||||
#include <qfile.h>
|
||||
#include <qdir.h>
|
||||
@ -96,7 +97,7 @@ int runUic(int argc, char *argv[])
|
||||
|
||||
QCommandLineOption generatorOption(QStringList() << QStringLiteral("g") << QStringLiteral("generator"));
|
||||
generatorOption.setDescription(QStringLiteral("Select generator."));
|
||||
generatorOption.setValueName(QStringLiteral("java|cpp"));
|
||||
generatorOption.setValueName(QStringLiteral("python|cpp"));
|
||||
parser.addOption(generatorOption);
|
||||
|
||||
QCommandLineOption idBasedOption(QStringLiteral("idbased"));
|
||||
@ -116,6 +117,13 @@ int runUic(int argc, char *argv[])
|
||||
driver.option().translateFunction = parser.value(translateOption);
|
||||
driver.option().includeFile = parser.value(includeOption);
|
||||
|
||||
Language language = Language::Cpp;
|
||||
if (parser.isSet(generatorOption)) {
|
||||
if (parser.value(generatorOption).compare(QLatin1String("python")) == 0)
|
||||
language = Language::Python;
|
||||
}
|
||||
language::setLanguage(language);
|
||||
|
||||
if (parser.isSet(noStringLiteralOption))
|
||||
fprintf(stderr, "The -s, --no-stringliteral option is deprecated and it won't take any effect.\n");
|
||||
|
||||
|
8
src/tools/uic/python/python.pri
Normal file
8
src/tools/uic/python/python.pri
Normal file
@ -0,0 +1,8 @@
|
||||
INCLUDEPATH += $$PWD
|
||||
|
||||
# Input
|
||||
HEADERS += $$PWD/pythonwritedeclaration.h \
|
||||
$$PWD/pythonwriteimports.h
|
||||
|
||||
SOURCES += $$PWD/pythonwritedeclaration.cpp \
|
||||
$$PWD/pythonwriteimports.cpp
|
73
src/tools/uic/python/pythonwritedeclaration.cpp
Normal file
73
src/tools/uic/python/pythonwritedeclaration.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the tools applications of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "pythonwritedeclaration.h"
|
||||
#include <cppwriteinitialization.h>
|
||||
#include <language.h>
|
||||
#include <driver.h>
|
||||
#include <ui4.h>
|
||||
#include <uic.h>
|
||||
|
||||
#include <QtCore/qtextstream.h>
|
||||
#include <QtCore/qdebug.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace Python {
|
||||
|
||||
WriteDeclaration::WriteDeclaration(Uic *uic) :
|
||||
m_uic(uic),
|
||||
m_driver(uic->driver()),
|
||||
m_output(uic->output()),
|
||||
m_option(uic->option())
|
||||
{
|
||||
}
|
||||
|
||||
void WriteDeclaration::acceptUI(DomUI *node)
|
||||
{
|
||||
// remove any left-over C++ namespaces
|
||||
const QString qualifiedClassName = QLatin1String("Ui_") + node->elementClass()
|
||||
+ m_option.postfix;
|
||||
m_output << "class " << language::fixClassName(qualifiedClassName) << "(object):\n";
|
||||
|
||||
TreeWalker::acceptWidget(node->elementWidget());
|
||||
if (const DomButtonGroups *domButtonGroups = node->elementButtonGroups())
|
||||
acceptButtonGroups(domButtonGroups);
|
||||
CPP::WriteInitialization(m_uic).acceptUI(node);
|
||||
}
|
||||
|
||||
// Register button groups to prevent the on-the-fly creation legacy
|
||||
// feature from triggering
|
||||
void WriteDeclaration::acceptButtonGroup(const DomButtonGroup *buttonGroup)
|
||||
{
|
||||
m_driver->findOrInsertButtonGroup(buttonGroup);
|
||||
}
|
||||
|
||||
} // namespace Python
|
||||
|
||||
QT_END_NAMESPACE
|
62
src/tools/uic/python/pythonwritedeclaration.h
Normal file
62
src/tools/uic/python/pythonwritedeclaration.h
Normal file
@ -0,0 +1,62 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the tools applications of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef PYTHONWRITEDECLARATION_H
|
||||
#define PYTHONWRITEDECLARATION_H
|
||||
|
||||
#include <treewalker.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QTextStream;
|
||||
class Driver;
|
||||
class Uic;
|
||||
|
||||
struct Option;
|
||||
|
||||
namespace Python {
|
||||
|
||||
struct WriteDeclaration : public TreeWalker
|
||||
{
|
||||
WriteDeclaration(Uic *uic);
|
||||
|
||||
void acceptUI(DomUI *node) override;
|
||||
void acceptButtonGroup(const DomButtonGroup *buttonGroup) override;
|
||||
|
||||
private:
|
||||
Uic *m_uic;
|
||||
Driver *m_driver;
|
||||
QTextStream &m_output;
|
||||
const Option &m_option;
|
||||
};
|
||||
|
||||
} // namespace Python
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // PYTHONWRITEDECLARATION_H
|
92
src/tools/uic/python/pythonwriteimports.cpp
Normal file
92
src/tools/uic/python/pythonwriteimports.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the tools applications of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "pythonwriteimports.h"
|
||||
|
||||
#include <customwidgetsinfo.h>
|
||||
#include <uic.h>
|
||||
|
||||
#include <ui4.h>
|
||||
|
||||
#include <QtCore/qtextstream.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
static const char *standardImports =
|
||||
R"I(from PySide2.QtCore import (QCoreApplication, QMetaObject, QObject, QPoint,
|
||||
QRect, QSize, QUrl, Qt)
|
||||
from PySide2.QtGui import (QColor, QFont, QIcon, QPixmap)
|
||||
from PySide2.QtWidgets import *
|
||||
)I";
|
||||
|
||||
namespace Python {
|
||||
|
||||
WriteImports::WriteImports(Uic *uic) : m_uic(uic)
|
||||
{
|
||||
}
|
||||
|
||||
void WriteImports::acceptUI(DomUI *node)
|
||||
{
|
||||
auto &output = m_uic->output();
|
||||
output << standardImports << '\n';
|
||||
if (auto customWidgets = node->elementCustomWidgets()) {
|
||||
TreeWalker::acceptCustomWidgets(customWidgets);
|
||||
output << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
QString WriteImports::qtModuleOf(const DomCustomWidget *node) const
|
||||
{
|
||||
if (m_uic->customWidgetsInfo()->extends(node->elementClass(), QLatin1String("QAxWidget")))
|
||||
return QStringLiteral("QtAxContainer");
|
||||
if (const auto headerElement = node->elementHeader()) {
|
||||
const auto &header = headerElement->text();
|
||||
if (header.startsWith(QLatin1String("Qt"))) {
|
||||
const int slash = header.indexOf(QLatin1Char('/'));
|
||||
if (slash != -1)
|
||||
return header.left(slash);
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
void WriteImports::acceptCustomWidget(DomCustomWidget *node)
|
||||
{
|
||||
const auto &className = node->elementClass();
|
||||
if (className.contains(QLatin1String("::")))
|
||||
return; // Exclude namespaced names (just to make tests pass).
|
||||
const QString &qtModule = qtModuleOf(node);
|
||||
auto &output = m_uic->output();
|
||||
if (!qtModule.isEmpty())
|
||||
output << "from PySide2." << qtModule << ' ';
|
||||
output << "import " << className << '\n';
|
||||
}
|
||||
|
||||
} // namespace Python
|
||||
|
||||
QT_END_NAMESPACE
|
58
src/tools/uic/python/pythonwriteimports.h
Normal file
58
src/tools/uic/python/pythonwriteimports.h
Normal file
@ -0,0 +1,58 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the tools applications of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef PYTHONWRITEIMPORTS_H
|
||||
#define PYTHONWRITEIMPORTS_H
|
||||
|
||||
#include <treewalker.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class Uic;
|
||||
|
||||
namespace Python {
|
||||
|
||||
struct WriteImports : public TreeWalker
|
||||
{
|
||||
public:
|
||||
explicit WriteImports(Uic *uic);
|
||||
|
||||
void acceptUI(DomUI *node) override;
|
||||
void acceptCustomWidget(DomCustomWidget *node) override;
|
||||
|
||||
private:
|
||||
QString qtModuleOf(const DomCustomWidget *node) const;
|
||||
|
||||
Uic *const m_uic;
|
||||
};
|
||||
|
||||
} // namespace Python
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // PYTHONWRITEIMPORTS_H
|
@ -33,6 +33,48 @@
|
||||
namespace language {
|
||||
|
||||
static Encoding encoding = Encoding::Utf8;
|
||||
static Language _language = Language::Cpp;
|
||||
|
||||
Language language() { return _language; }
|
||||
|
||||
void setLanguage(Language l)
|
||||
{
|
||||
_language = l;
|
||||
switch (_language) {
|
||||
case Language::Cpp:
|
||||
derefPointer = QLatin1String("->");
|
||||
nullPtr = QLatin1String("nullptr");
|
||||
operatorNew = QLatin1String("new ");
|
||||
qtQualifier = QLatin1String("Qt::");
|
||||
qualifier = QLatin1String("::");
|
||||
self = QLatin1String(""); // for testing: change to "this->";
|
||||
eol = QLatin1String(";\n");
|
||||
encoding = Encoding::Utf8;
|
||||
break;
|
||||
case Language::Python:
|
||||
derefPointer = QLatin1String(".");
|
||||
nullPtr = QLatin1String("None");
|
||||
operatorNew = QLatin1String("");
|
||||
qtQualifier = QLatin1String("Qt.");
|
||||
qualifier = QLatin1String(".");
|
||||
self = QLatin1String("self.");
|
||||
eol = QLatin1String("\n");
|
||||
encoding = Encoding::Unicode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QString derefPointer;
|
||||
QString nullPtr;
|
||||
QString operatorNew;
|
||||
QString qtQualifier;
|
||||
QString qualifier;
|
||||
QString self;
|
||||
QString eol;
|
||||
|
||||
QString cppQualifier = QLatin1String("::");
|
||||
QString cppTrue = QLatin1String("true");
|
||||
QString cppFalse = QLatin1String("false");
|
||||
|
||||
QTextStream &operator<<(QTextStream &str, const qtConfig &c)
|
||||
{
|
||||
@ -71,6 +113,13 @@ const char *lookupEnum(const EnumLookup(&array)[N], int value, int defaultIndex
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
QString fixClassName(QString className)
|
||||
{
|
||||
if (language() == Language::Python)
|
||||
className.replace(cppQualifier, QLatin1String("_"));
|
||||
return className;
|
||||
}
|
||||
|
||||
const char *toolbarArea(int v)
|
||||
{
|
||||
static const EnumLookup toolBarAreas[] =
|
||||
@ -250,12 +299,12 @@ void _formatString(QTextStream &str, const QString &value, const QString &indent
|
||||
switch (encoding) {
|
||||
// Special characters as 3 digit octal escapes (u8"\303\234mlaut")
|
||||
case Encoding::Utf8: {
|
||||
if (qString)
|
||||
if (qString && _language == Language::Cpp)
|
||||
str << "QString::fromUtf8(";
|
||||
const QByteArray utf8 = value.toUtf8();
|
||||
formatStringSequence<Encoding::Utf8>(str, utf8.cbegin(), utf8.cend(), indent,
|
||||
8, 3);
|
||||
if (qString)
|
||||
if (qString && _language == Language::Cpp)
|
||||
str << ')';
|
||||
}
|
||||
break;
|
||||
@ -268,4 +317,71 @@ void _formatString(QTextStream &str, const QString &value, const QString &indent
|
||||
}
|
||||
}
|
||||
|
||||
QTextStream &operator<<(QTextStream &str, const repeat &r)
|
||||
{
|
||||
for (int i = 0; i < r.m_count; ++i)
|
||||
str << r.m_char;
|
||||
return str;
|
||||
}
|
||||
|
||||
startFunctionDefinition1::startFunctionDefinition1(const char *name, const QString ¶meterType,
|
||||
const QString ¶meterName,
|
||||
const QString &indent,
|
||||
const char *returnType) :
|
||||
m_name(name), m_parameterType(parameterType), m_parameterName(parameterName),
|
||||
m_indent(indent), m_return(returnType)
|
||||
{
|
||||
}
|
||||
|
||||
QTextStream &operator<<(QTextStream &str, const startFunctionDefinition1 &f)
|
||||
{
|
||||
switch (language()) {
|
||||
case Language::Cpp:
|
||||
str << (f.m_return ? f.m_return : "void") << ' ' << f.m_name << '('
|
||||
<< f.m_parameterType;
|
||||
if (f.m_parameterType.cend()->isLetter())
|
||||
str << ' ';
|
||||
str << f.m_parameterName << ')' << '\n' << f.m_indent << "{\n";
|
||||
break;
|
||||
case Language::Python:
|
||||
str << "def " << f.m_name << "(self, " << f.m_parameterName << "):\n";
|
||||
break;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
endFunctionDefinition::endFunctionDefinition(const char *name) : m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
QTextStream &operator<<(QTextStream &str, const endFunctionDefinition &f)
|
||||
{
|
||||
switch (language()) {
|
||||
case Language::Cpp:
|
||||
str << "} // " << f.m_name << "\n\n";
|
||||
break;
|
||||
case Language::Python:
|
||||
str << "# " << f.m_name << "\n\n";
|
||||
break;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
void _formatStackVariable(QTextStream &str, const char *className, QStringView varName,
|
||||
bool withInitParameters)
|
||||
{
|
||||
switch (language()) {
|
||||
case Language::Cpp:
|
||||
str << className << ' ' << varName;
|
||||
if (withInitParameters)
|
||||
str << '(';
|
||||
break;
|
||||
case Language::Python:
|
||||
str << varName << " = " << className << '(';
|
||||
if (!withInitParameters)
|
||||
str << ')';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace language
|
||||
|
@ -34,8 +34,25 @@
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QTextStream)
|
||||
|
||||
enum class Language { Cpp, Python };
|
||||
|
||||
namespace language {
|
||||
|
||||
Language language();
|
||||
void setLanguage(Language);
|
||||
|
||||
extern QString derefPointer;
|
||||
extern QString nullPtr;
|
||||
extern QString operatorNew;
|
||||
extern QString qtQualifier;
|
||||
extern QString qualifier;
|
||||
extern QString self;
|
||||
extern QString eol;
|
||||
|
||||
extern QString cppQualifier;
|
||||
extern QString cppTrue;
|
||||
extern QString cppFalse;
|
||||
|
||||
// Base class for streamable objects with one QStringView parameter
|
||||
class StringViewStreamable
|
||||
{
|
||||
@ -72,6 +89,8 @@ public:
|
||||
|
||||
QTextStream &operator<<(QTextStream &, const closeQtConfig &c);
|
||||
|
||||
QString fixClassName(QString className);
|
||||
|
||||
const char *toolbarArea(int v);
|
||||
const char *sizePolicy(int v);
|
||||
const char *dockWidgetArea(int v);
|
||||
@ -107,6 +126,69 @@ inline QTextStream &operator<<(QTextStream &str, const language::_string<AsQStri
|
||||
using charliteral = _string<false>;
|
||||
using qstring = _string<true>;
|
||||
|
||||
class repeat {
|
||||
public:
|
||||
explicit repeat(int count, char c) : m_count(count), m_char(c) {}
|
||||
|
||||
friend QTextStream &operator<<(QTextStream &str, const repeat &r);
|
||||
|
||||
private:
|
||||
const int m_count;
|
||||
const char m_char;
|
||||
};
|
||||
|
||||
class startFunctionDefinition1 {
|
||||
public:
|
||||
explicit startFunctionDefinition1(const char *name, const QString ¶meterType,
|
||||
const QString ¶meterName,
|
||||
const QString &indent,
|
||||
const char *returnType = nullptr);
|
||||
|
||||
friend QTextStream &operator<<(QTextStream &str, const startFunctionDefinition1 &f);
|
||||
private:
|
||||
const char *m_name;
|
||||
const QString &m_parameterType;
|
||||
const QString &m_parameterName;
|
||||
const QString &m_indent;
|
||||
const char *m_return;
|
||||
};
|
||||
|
||||
class endFunctionDefinition {
|
||||
public:
|
||||
explicit endFunctionDefinition(const char *name);
|
||||
|
||||
friend QTextStream &operator<<(QTextStream &str, const endFunctionDefinition &f);
|
||||
private:
|
||||
const char *m_name;
|
||||
};
|
||||
|
||||
void _formatStackVariable(QTextStream &str, const char *className, QStringView varName, bool withInitParameters);
|
||||
|
||||
template <bool withInitParameters>
|
||||
class _stackVariable {
|
||||
public:
|
||||
explicit _stackVariable(const char *className, QStringView varName) :
|
||||
m_className(className), m_varName(varName) {}
|
||||
|
||||
void format(QTextStream &str) const
|
||||
{ _formatStackVariable(str, m_className, m_varName, withInitParameters); }
|
||||
|
||||
private:
|
||||
const char *m_className;
|
||||
QStringView m_varName;
|
||||
QStringView m_parameters;
|
||||
};
|
||||
|
||||
template <bool withInitParameters>
|
||||
inline QTextStream &operator<<(QTextStream &str, const _stackVariable<withInitParameters> &s)
|
||||
{
|
||||
s.format(str);
|
||||
return str;
|
||||
}
|
||||
|
||||
using stackVariable = _stackVariable<false>;
|
||||
using stackVariableWithInitParameters = _stackVariable<true>;
|
||||
|
||||
} // namespace language
|
||||
|
||||
#endif // LANGUAGE_H
|
||||
|
@ -35,6 +35,10 @@
|
||||
|
||||
#include "cppwriteincludes.h"
|
||||
#include "cppwritedeclaration.h"
|
||||
#include <pythonwritedeclaration.h>
|
||||
#include <pythonwriteimports.h>
|
||||
|
||||
#include <language.h>
|
||||
|
||||
#include <qxmlstream.h>
|
||||
#include <qfileinfo.h>
|
||||
@ -103,7 +107,7 @@ bool Uic::printDependencies()
|
||||
return true;
|
||||
}
|
||||
|
||||
void Uic::writeCopyrightHeader(DomUI *ui)
|
||||
void Uic::writeCopyrightHeaderCpp(const DomUI *ui) const
|
||||
{
|
||||
QString comment = ui->elementComment();
|
||||
if (!comment.isEmpty())
|
||||
@ -118,6 +122,48 @@ void Uic::writeCopyrightHeader(DomUI *ui)
|
||||
out << "********************************************************************************/\n\n";
|
||||
}
|
||||
|
||||
// Format existing UI file comments for Python with some smartness : Replace all
|
||||
// leading C++ comment characters by '#' or prepend '#' if needed.
|
||||
|
||||
static inline bool isCppCommentChar(QChar c)
|
||||
{
|
||||
return c == QLatin1Char('/') || c == QLatin1Char('*');
|
||||
}
|
||||
|
||||
static int leadingCppCommentCharCount(const QStringRef &s)
|
||||
{
|
||||
int i = 0;
|
||||
for (const int size = s.size(); i < size && isCppCommentChar(s.at(i)); ++i) {
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void Uic::writeCopyrightHeaderPython(const DomUI *ui) const
|
||||
{
|
||||
QString comment = ui->elementComment();
|
||||
if (!comment.isEmpty()) {
|
||||
const auto lines = comment.splitRef(QLatin1Char('\n'));
|
||||
for (const auto &line : lines) {
|
||||
if (const int leadingCommentChars = leadingCppCommentCharCount(line)) {
|
||||
out << language::repeat(leadingCommentChars, '#')
|
||||
<< line.right(line.size() - leadingCommentChars);
|
||||
} else {
|
||||
if (!line.startsWith(QLatin1Char('#')))
|
||||
out << "# ";
|
||||
out << line;
|
||||
}
|
||||
out << '\n';
|
||||
}
|
||||
out << '\n';
|
||||
}
|
||||
|
||||
out << language::repeat(80, '#') << "\n## Form generated from reading UI file '"
|
||||
<< QFileInfo(opt.inputFile).fileName()
|
||||
<< "'\n##\n## Created by: Qt User Interface Compiler version " << QT_VERSION_STR
|
||||
<< "\n##\n## WARNING! All changes made in this file will be lost when recompiling UI file!\n"
|
||||
<< language::repeat(80, '#') << "\n\n";
|
||||
}
|
||||
|
||||
// Check the version with a stream reader at the <ui> element.
|
||||
|
||||
static double versionFromUiAttribute(QXmlStreamReader &reader)
|
||||
@ -195,15 +241,26 @@ bool Uic::write(QIODevice *in)
|
||||
|
||||
bool Uic::write(DomUI *ui)
|
||||
{
|
||||
using namespace CPP;
|
||||
|
||||
if (!ui || !ui->elementWidget())
|
||||
return false;
|
||||
|
||||
if (opt.copyrightHeader)
|
||||
writeCopyrightHeader(ui);
|
||||
const auto lang = language::language();
|
||||
|
||||
if (opt.headerProtection) {
|
||||
if (lang == Language::Python)
|
||||
out << "# -*- coding: utf-8 -*-\n\n";
|
||||
|
||||
if (opt.copyrightHeader) {
|
||||
switch (language::language()) {
|
||||
case Language::Cpp:
|
||||
writeCopyrightHeaderCpp(ui);
|
||||
break;
|
||||
case Language::Python:
|
||||
writeCopyrightHeaderPython(ui);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (opt.headerProtection && lang == Language::Cpp) {
|
||||
writeHeaderProtectionStart();
|
||||
out << "\n";
|
||||
}
|
||||
@ -218,13 +275,25 @@ bool Uic::write(DomUI *ui)
|
||||
|
||||
info.acceptUI(ui);
|
||||
cWidgetsInfo.acceptUI(ui);
|
||||
WriteIncludes writeIncludes(this);
|
||||
|
||||
switch (language::language()) {
|
||||
case Language::Cpp: {
|
||||
CPP::WriteIncludes writeIncludes(this);
|
||||
writeIncludes.acceptUI(ui);
|
||||
|
||||
Validator(this).acceptUI(ui);
|
||||
WriteDeclaration(this).acceptUI(ui);
|
||||
CPP::WriteDeclaration(this).acceptUI(ui);
|
||||
}
|
||||
break;
|
||||
case Language::Python: {
|
||||
Python::WriteImports writeImports(this);
|
||||
writeImports.acceptUI(ui);
|
||||
Validator(this).acceptUI(ui);
|
||||
Python::WriteDeclaration(this).acceptUI(ui);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (opt.headerProtection)
|
||||
if (opt.headerProtection && lang == Language::Cpp)
|
||||
writeHeaderProtectionEnd();
|
||||
|
||||
return true;
|
||||
|
@ -91,7 +91,8 @@ public:
|
||||
|
||||
private:
|
||||
// copyright header
|
||||
void writeCopyrightHeader(DomUI *ui);
|
||||
void writeCopyrightHeaderCpp(const DomUI *ui) const;
|
||||
void writeCopyrightHeaderPython(const DomUI *ui) const;
|
||||
DomUI *parseUiFile(QXmlStreamReader &reader);
|
||||
|
||||
// header protection
|
||||
|
@ -7,6 +7,7 @@ DEFINES += QT_UIC QT_NO_CAST_FROM_ASCII QT_NO_FOREACH
|
||||
include(uic.pri)
|
||||
include(shared/shared.pri)
|
||||
include(cpp/cpp.pri)
|
||||
include(python/python.pri)
|
||||
|
||||
HEADERS += uic.h
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user