Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#include "uic.h"
5#include "option.h"
6#include "driver.h"
7#include <language.h>
8
9#include <qfile.h>
10#include <qdir.h>
11#include <qhashfunctions.h>
12#include <qtextstream.h>
13#include <qcoreapplication.h>
14#include <qcommandlineoption.h>
15#include <qcommandlineparser.h>
16#include <qfileinfo.h>
17
18QT_BEGIN_NAMESPACE
19
20using namespace Qt::StringLiterals;
21
22static const char pythonPathVar[] = "PYTHONPATH";
23
24// From the Python paths, find the component the UI file is under
25static QString pythonRoot(const QString &pythonPath, const QString &uiFileIn)
26{
27#ifdef Q_OS_WIN
28 static const Qt::CaseSensitivity fsSensitivity = Qt::CaseInsensitive;
29#else
30 static const Qt::CaseSensitivity fsSensitivity = Qt::CaseSensitive;
31#endif
32
33 if (pythonPath.isEmpty() || uiFileIn.isEmpty())
34 return {};
35 const QString uiFile = QFileInfo(uiFileIn).canonicalFilePath();
36 if (uiFile.isEmpty())
37 return {};
38 const auto uiFileSize = uiFile.size();
39 const auto paths = pythonPath.split(QDir::listSeparator(), Qt::SkipEmptyParts);
40 for (const auto &path : paths) {
41 const QString canonicalPath = QFileInfo(path).canonicalFilePath();
42 const auto canonicalPathSize = canonicalPath.size();
43 if (uiFileSize > canonicalPathSize
44 && uiFile.at(canonicalPathSize) == u'/'
45 && uiFile.startsWith(canonicalPath, fsSensitivity)) {
46 return canonicalPath;
47 }
48 }
49 return {};
50}
51
52int runUic(int argc, char *argv[])
53{
54 QHashSeed::setDeterministicGlobalSeed();
55
56 QCoreApplication app(argc, argv);
57 const QString version = QString::fromLatin1(qVersion());
58 QCoreApplication::setApplicationVersion(version);
59
60 Driver driver;
61
62 // Note that uic isn't translated.
63 // If you use this code as an example for a translated app, make sure to translate the strings.
64 QCommandLineParser parser;
65 parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
66 parser.setApplicationDescription(u"Qt User Interface Compiler version %1"_s.arg(version));
67 parser.addHelpOption();
68 parser.addVersionOption();
69
70 QCommandLineOption dependenciesOption(QStringList{u"d"_s, u"dependencies"_s});
71 dependenciesOption.setDescription(u"Display the dependencies."_s);
72 parser.addOption(dependenciesOption);
73
74 QCommandLineOption outputOption(QStringList{u"o"_s, u"output"_s});
75 outputOption.setDescription(u"Place the output into <file>"_s);
76 outputOption.setValueName(u"file"_s);
77 parser.addOption(outputOption);
78
79 QCommandLineOption noAutoConnectionOption(QStringList{u"a"_s, u"no-autoconnection"_s});
80 noAutoConnectionOption.setDescription(u"Do not generate a call to QObject::connectSlotsByName()."_s);
81 parser.addOption(noAutoConnectionOption);
82
83 QCommandLineOption noProtOption(QStringList{u"p"_s, u"no-protection"_s});
84 noProtOption.setDescription(u"Disable header protection."_s);
85 parser.addOption(noProtOption);
86
87 QCommandLineOption noImplicitIncludesOption(QStringList{u"n"_s, u"no-implicit-includes"_s});
88 noImplicitIncludesOption.setDescription(u"Disable generation of #include-directives."_s);
89 parser.addOption(noImplicitIncludesOption);
90
91 QCommandLineOption postfixOption(u"postfix"_s);
92 postfixOption.setDescription(u"Postfix to add to all generated classnames."_s);
93 postfixOption.setValueName(u"postfix"_s);
94 parser.addOption(postfixOption);
95
96 QCommandLineOption noQtNamespaceOption(u"no-qt-namespace"_s);
97 noQtNamespaceOption.setDescription(
98 u"Disable wrapping the definition of the generated class in QT_{BEGIN,END}_NAMESPACE."_s);
99 parser.addOption(noQtNamespaceOption);
100
101 QCommandLineOption translateOption(QStringList{u"tr"_s, u"translate"_s});
102 translateOption.setDescription(u"Use <function> for i18n."_s);
103 translateOption.setValueName(u"function"_s);
104 parser.addOption(translateOption);
105
106 QCommandLineOption includeOption(QStringList{u"include"_s});
107 includeOption.setDescription(u"Add #include <include-file> to <file>."_s);
108 includeOption.setValueName(u"include-file"_s);
109 parser.addOption(includeOption);
110
111 QCommandLineOption generatorOption(QStringList{u"g"_s, u"generator"_s});
112 generatorOption.setDescription(u"Select generator."_s);
113 generatorOption.setValueName(u"python|cpp"_s);
114 parser.addOption(generatorOption);
115
116 QCommandLineOption connectionsOption(QStringList{u"c"_s, u"connections"_s});
117 connectionsOption.setDescription(u"Connection syntax."_s);
118 connectionsOption.setValueName(u"pmf|string"_s);
119 parser.addOption(connectionsOption);
120
121 QCommandLineOption idBasedOption(u"idbased"_s);
122 idBasedOption.setDescription(u"Use id based function for i18n"_s);
123 parser.addOption(idBasedOption);
124
125 QCommandLineOption fromImportsOption(u"from-imports"_s);
126 fromImportsOption.setDescription(u"Python: generate imports relative to '.'"_s);
127 parser.addOption(fromImportsOption);
128
129 QCommandLineOption absoluteImportsOption(u"absolute-imports"_s);
130 absoluteImportsOption.setDescription(u"Python: generate absolute imports"_s);
131 parser.addOption(absoluteImportsOption);
132
133 // FIXME Qt 7: Flip the default?
134 QCommandLineOption rcPrefixOption(u"rc-prefix"_s);
135 rcPrefixOption.setDescription(uR"(Python: Generate "rc_file" instead of "file_rc" import)"_s);
136 parser.addOption(rcPrefixOption);
137
138 // FIXME Qt 7: Remove?
139 QCommandLineOption useStarImportsOption(u"star-imports"_s);
140 useStarImportsOption.setDescription(u"Python: Use * imports"_s);
141 parser.addOption(useStarImportsOption);
142
143 QCommandLineOption pythonPathOption(u"python-paths"_s);
144 pythonPathOption.setDescription(u"Python paths for --absolute-imports."_s);
145 pythonPathOption.setValueName(u"pathlist"_s);
146 parser.addOption(pythonPathOption);
147
148 parser.addPositionalArgument(u"[uifile]"_s, u"Input file (*.ui), otherwise stdin."_s);
149
150 parser.process(app);
151
152 driver.option().dependencies = parser.isSet(dependenciesOption);
153 driver.option().outputFile = parser.value(outputOption);
154 driver.option().autoConnection = !parser.isSet(noAutoConnectionOption);
155 driver.option().headerProtection = !parser.isSet(noProtOption);
156 driver.option().implicitIncludes = !parser.isSet(noImplicitIncludesOption);
157 driver.option().qtNamespace = !parser.isSet(noQtNamespaceOption);
158 driver.option().idBased = parser.isSet(idBasedOption);
159 driver.option().postfix = parser.value(postfixOption);
160 driver.option().translateFunction = parser.value(translateOption);
161 driver.option().includeFile = parser.value(includeOption);
162 if (parser.isSet(connectionsOption)) {
163 const auto value = parser.value(connectionsOption);
164 if (value == "pmf"_L1)
166 else if (value == "string"_L1)
168 }
169
170 const QString inputFile = parser.positionalArguments().value(0);
171
172 Language language = Language::Cpp;
173 if (parser.isSet(generatorOption)) {
174 if (parser.value(generatorOption).compare("python"_L1) == 0)
175 language = Language::Python;
176 }
178 if (language == Language::Python) {
179 if (parser.isSet(fromImportsOption))
181 else if (parser.isSet(absoluteImportsOption))
183 driver.option().useStarImports = parser.isSet(useStarImportsOption);
184 if (parser.isSet(rcPrefixOption))
185 driver.option().rcPrefix = 1;
186 QString pythonPaths;
187 if (parser.isSet(pythonPathOption))
188 pythonPaths = parser.value(pythonPathOption);
189 else if (qEnvironmentVariableIsSet(pythonPathVar))
190 pythonPaths = qEnvironmentVariable(pythonPathVar);
191 driver.option().pythonRoot = pythonRoot(pythonPaths, inputFile);
192 }
193
194 if (inputFile.isEmpty()) // reading from stdin
195 driver.option().headerProtection = false;
196
197 if (driver.option().dependencies) {
198 return !driver.printDependencies(inputFile);
199 }
200
201 QTextStream *out = nullptr;
202 QFile f;
203 if (!driver.option().outputFile.isEmpty()) {
204 f.setFileName(driver.option().outputFile);
205 if (!f.open(QIODevice::WriteOnly | QFile::Text)) {
206 fprintf(stderr, "Could not create output file\n");
207 return 1;
208 }
209 out = new QTextStream(&f);
210 out->setEncoding(QStringConverter::Utf8);
211 }
212
213 bool rtn = driver.uic(inputFile, out);
214 delete out;
215
216 if (!rtn) {
217 if (driver.option().outputFile.size()) {
218 f.close();
219 f.remove();
220 }
221 fprintf(stderr, "File '%s' is not valid\n", inputFile.isEmpty() ? "<stdin>" : inputFile.toLocal8Bit().constData());
222 }
223
224 return !rtn;
225}
226
228
229int main(int argc, char *argv[])
230{
231 return QT_PREPEND_NAMESPACE(runUic)(argc, argv);
232}
Option & option()
Definition driver.h:39
bool printDependencies(const QString &fileName)
Definition driver.cpp:218
The QCommandLineOption class defines a possible command-line option. \inmodule QtCore.
The QCommandLineParser class provides a means for handling the command line options.
\inmodule QtCore
Definition qfile.h:96
Language
Definition language.h:12
void setLanguage(Language)
Definition language.cpp:20
static QString pythonRoot(const QString &pythonPath, const QString &uiFileIn)
Definition main.cpp:25
static const char pythonPathVar[]
Definition main.cpp:22
int runUic(int argc, char *argv[])
Definition main.cpp:52
int main(int argc, char *argv[])
[ctor_close]
unsigned int headerProtection
Definition option.h:20
unsigned int rcPrefix
Definition option.h:32
unsigned int forceMemberFnPtrConnectionSyntax
Definition option.h:29
unsigned int forceStringConnectionSyntax
Definition option.h:30
unsigned int dependencies
Definition option.h:25
PythonResourceImport
Definition option.h:14
PythonResourceImport pythonResourceImport
Definition option.h:45