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