Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
uic.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 "ui4.h"
6#include "driver.h"
7#include "option.h"
8#include "treewalker.h"
9#include "validator.h"
10
11#include "cppwriteincludes.h"
12#include "cppwritedeclaration.h"
14#include <pythonwriteimports.h>
15
16#include <language.h>
17
18#include <qxmlstream.h>
19#include <qfileinfo.h>
20#include <qscopedpointer.h>
21#include <qtextstream.h>
22
24
25using namespace Qt::StringLiterals;
26
28 : drv(d),
29 out(d->output()),
30 opt(d->option())
31{
32}
33
34Uic::~Uic() = default;
35
37{
39
40 QFile f;
41 if (fileName.isEmpty()) {
42 if (!f.open(stdin, QIODevice::ReadOnly))
43 return false;
44 } else {
46 if (!f.open(QIODevice::ReadOnly))
47 return false;
48 }
49
50 DomUI *ui = nullptr;
51 {
52 QXmlStreamReader reader;
53 reader.setDevice(&f);
54 ui = parseUiFile(reader);
55 if (!ui)
56 return false;
57 }
58
59 if (DomIncludes *includes = ui->elementIncludes()) {
60 const auto incls = includes->elementInclude();
61 for (DomInclude *incl : incls) {
62 QString file = incl->text();
63 if (file.isEmpty())
64 continue;
65
66 fprintf(stdout, "%s\n", file.toLocal8Bit().constData());
67 }
68 }
69
70 if (DomCustomWidgets *customWidgets = ui->elementCustomWidgets()) {
71 const auto elementCustomWidget = customWidgets->elementCustomWidget();
72 for (DomCustomWidget *customWidget : elementCustomWidget) {
73 if (DomHeader *header = customWidget->elementHeader()) {
74 QString file = header->text();
75 if (file.isEmpty())
76 continue;
77
78 fprintf(stdout, "%s\n", file.toLocal8Bit().constData());
79 }
80 }
81 }
82
83 delete ui;
84
85 return true;
86}
87
88void Uic::writeCopyrightHeaderCpp(const DomUI *ui) const
89{
90 QString comment = ui->elementComment();
91 if (!comment.isEmpty())
92 out << "/*\n" << comment << "\n*/\n\n";
93
94 out << "/********************************************************************************\n";
95 out << "** Form generated from reading UI file '" << QFileInfo(opt.inputFile).fileName() << "'\n";
96 out << "**\n";
97 out << "** Created by: Qt User Interface Compiler version " << QT_VERSION_STR << "\n";
98 out << "**\n";
99 out << "** WARNING! All changes made in this file will be lost when recompiling UI file!\n";
100 out << "********************************************************************************/\n\n";
101}
102
103// Format existing UI file comments for Python with some smartness : Replace all
104// leading C++ comment characters by '#' or prepend '#' if needed.
105
106static inline bool isCppCommentChar(QChar c)
107{
108 return c == u'/' || c == u'*';
109}
110
112{
113 int i = 0;
114 for (const int size = s.size(); i < size && isCppCommentChar(s.at(i)); ++i) {
115 }
116 return i;
117}
118
119void Uic::writeCopyrightHeaderPython(const DomUI *ui) const
120{
121 QString comment = ui->elementComment();
122 if (!comment.isEmpty()) {
123 const auto lines = QStringView{comment}.split(u'\n');
124 for (const auto &line : lines) {
125 if (const int leadingCommentChars = leadingCppCommentCharCount(line)) {
126 out << language::repeat(leadingCommentChars, '#')
127 << line.right(line.size() - leadingCommentChars);
128 } else {
129 if (!line.startsWith(u'#'))
130 out << "# ";
131 out << line;
132 }
133 out << '\n';
134 }
135 out << '\n';
136 }
137
138 out << language::repeat(80, '#') << "\n## Form generated from reading UI file '"
140 << "'\n##\n## Created by: Qt User Interface Compiler version " << QT_VERSION_STR
141 << "\n##\n## WARNING! All changes made in this file will be lost when recompiling UI file!\n"
142 << language::repeat(80, '#') << "\n\n";
143}
144
145// Check the version with a stream reader at the <ui> element.
146
147static double versionFromUiAttribute(QXmlStreamReader &reader)
148{
149 const QXmlStreamAttributes attributes = reader.attributes();
150 const auto versionAttribute = "version"_L1;
151 if (!attributes.hasAttribute(versionAttribute))
152 return 4.0;
153 const QStringView version = attributes.value(versionAttribute);
154 return version.toDouble();
155}
156
157DomUI *Uic::parseUiFile(QXmlStreamReader &reader)
158{
159 DomUI *ui = nullptr;
160
161 const auto uiElement = "ui"_L1;
162 while (!reader.atEnd()) {
163 if (reader.readNext() == QXmlStreamReader::StartElement) {
164 if (reader.name().compare(uiElement, Qt::CaseInsensitive) == 0
165 && !ui) {
166 const double version = versionFromUiAttribute(reader);
167 if (version < 4.0) {
168 const QString msg = QString::fromLatin1("uic: File generated with too old version of Qt Widgets Designer (%1)").arg(version);
169 fprintf(stderr, "%s\n", qPrintable(msg));
170 return nullptr;
171 }
172
173 ui = new DomUI();
174 ui->read(reader);
175 } else {
176 reader.raiseError("Unexpected element "_L1 + reader.name().toString());
177 }
178 }
179 }
180 if (reader.hasError()) {
181 delete ui;
182 ui = nullptr;
183 fprintf(stderr, "%s\n", qPrintable(QString::fromLatin1("uic: Error in line %1, column %2 : %3")
184 .arg(reader.lineNumber()).arg(reader.columnNumber())
185 .arg(reader.errorString())));
186 }
187
188 return ui;
189}
190
192{
193 QScopedPointer<DomUI> ui;
194 {
195 QXmlStreamReader reader;
196 reader.setDevice(in);
197 ui.reset(parseUiFile(reader));
198 }
199
200 if (ui.isNull())
201 return false;
202
203 double version = ui->attributeVersion().toDouble();
204 if (version < 4.0) {
205 fprintf(stderr, "uic: File generated with too old version of Qt Widgets Designer\n");
206 return false;
207 }
208
209 const QString &language = ui->attributeLanguage();
210 driver()->setUseIdBasedTranslations(ui->attributeIdbasedtr());
211
212 if (!language.isEmpty() && language.compare("c++"_L1, Qt::CaseInsensitive) != 0) {
213 fprintf(stderr, "uic: File is not a \"c++\" ui file, language=%s\n", qPrintable(language));
214 return false;
215 }
216
217 return write(ui.data());
218}
219
221{
222 if (!ui || !ui->elementWidget())
223 return false;
224
225 const auto lang = language::language();
226
227 if (lang == Language::Python)
228 out << "# -*- coding: utf-8 -*-\n\n";
229
230 if (opt.copyrightHeader) {
231 switch (language::language()) {
232 case Language::Cpp:
233 writeCopyrightHeaderCpp(ui);
234 break;
235 case Language::Python:
236 writeCopyrightHeaderPython(ui);
237 break;
238 }
239 }
240
241 if (opt.headerProtection && lang == Language::Cpp) {
242 writeHeaderProtectionStart();
243 out << "\n";
244 }
245
246 pixFunction = ui->elementPixmapFunction();
247 if (pixFunction == "QPixmap::fromMimeSource"_L1 || pixFunction == "qPixmapFromMimeSource"_L1) {
248 fprintf(stderr, "%s: Warning: Obsolete pixmap function '%s' specified in the UI file.\n",
249 qPrintable(opt.messagePrefix()), qPrintable(pixFunction));
250 pixFunction.clear();
251 }
252
253 info.acceptUI(ui);
254 cWidgetsInfo.acceptUI(ui);
255
256 switch (language::language()) {
257 case Language::Cpp: {
258 CPP::WriteIncludes writeIncludes(this);
259 writeIncludes.acceptUI(ui);
260 Validator(this).acceptUI(ui);
262 }
263 break;
264 case Language::Python: {
265 Python::WriteImports writeImports(this);
266 writeImports.acceptUI(ui);
267 Validator(this).acceptUI(ui);
269 }
270 break;
271 }
272
273 if (opt.headerProtection && lang == Language::Cpp)
274 writeHeaderProtectionEnd();
275
276 return true;
277}
278
279void Uic::writeHeaderProtectionStart()
280{
281 QString h = drv->headerFileName();
282 out << "#ifndef " << h << "\n"
283 << "#define " << h << "\n";
284}
285
286void Uic::writeHeaderProtectionEnd()
287{
288 QString h = drv->headerFileName();
289 out << "#endif // " << h << "\n";
290}
291
293{
294 static const QStringList buttons = {
295 u"QRadioButton"_s, u"QToolButton"_s,
296 u"QCheckBox"_s, u"QPushButton"_s,
297 u"QCommandLinkButton"_s
298 };
299 return customWidgetsInfo()->extendsOneOf(className, buttons);
300}
301
303{
304 static const QStringList containers = {
305 u"QStackedWidget"_s, u"QToolBox"_s,
306 u"QTabWidget"_s, u"QScrollArea"_s,
307 u"QMdiArea"_s, u"QWizard"_s,
308 u"QDockWidget"_s
309 };
310
311 return customWidgetsInfo()->extendsOneOf(className, containers);
312}
313
314bool Uic::isMenu(const QString &className) const
315{
316 static const QStringList menus = {
317 u"QMenu"_s, u"QPopupMenu"_s
318 };
319 return customWidgetsInfo()->extendsOneOf(className, menus);
320}
321
void acceptUI(DomUI *node) override
bool extendsOneOf(const QString &className, const QStringList &baseClassNames) const
void acceptUI(DomUI *node) override
Definition ui4.h:116
void setUseIdBasedTranslations(bool u)
Definition driver.h:68
static QString headerFileName(const QString &fileName)
Definition driver.cpp:196
\inmodule QtCore
QString fileName() const
\inmodule QtCore
Definition qfile.h:93
void setFileName(const QString &name)
Sets the name of the file.
Definition qfile.cpp:302
\inmodule QtCore \reentrant
Definition qiodevice.h:34
QString errorString() const
Returns a human readable description of the last error that occurred.
void setDevice(QIODevice *device)
Sets QImageReader's device to device.
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:78
Q_CORE_EXPORT double toDouble(bool *ok=nullptr) const
Returns the string view converted to a double value.
Definition qstring.cpp:7909
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5455
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the string into substrings wherever sep occurs, and returns the list of those strings.
Definition qstring.cpp:8218
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1252
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
QString right(qsizetype n) const &
Definition qstring.h:375
bool printDependencies()
Definition uic.cpp:36
Uic(Driver *driver)
Definition uic.cpp:27
bool isButton(const QString &className) const
Definition uic.cpp:292
~Uic()
bool write(QIODevice *in)
Definition uic.cpp:191
const CustomWidgetsInfo * customWidgetsInfo() const
Definition uic.h:56
bool isMenu(const QString &className) const
Definition uic.cpp:314
bool isContainer(const QString &className) const
Definition uic.cpp:302
Driver * driver() const
Definition uic.h:38
QStyleOptionButton opt
Combined button and popup list for selecting options.
@ CaseInsensitive
Language language()
Definition language.cpp:16
QImageReader reader("image.png")
[1]
static QString header(const QString &name)
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLfloat GLfloat f
GLfloat GLfloat GLfloat GLfloat h
GLdouble s
[6]
Definition qopenglext.h:235
const GLubyte * c
GLuint in
GLuint GLenum option
SSL_CTX int void * arg
#define qPrintable(string)
Definition qstring.h:1531
QT_BEGIN_NAMESPACE typedef uchar * output
const char className[16]
[1]
Definition qwizard.cpp:100
QFile file
[0]
QTextStream out(stdout)
[7]
void acceptUI(DomUI *node) override
unsigned int headerProtection
Definition option.h:20
QString messagePrefix() const
Definition option.h:65
QString inputFile
Definition option.h:35
unsigned int copyrightHeader
Definition option.h:21
void acceptUI(DomUI *node) override
void acceptUI(DomUI *node) override
Definition validator.cpp:16
static double versionFromUiAttribute(QXmlStreamReader &reader)
Definition uic.cpp:147
static int leadingCppCommentCharCount(QStringView s)
Definition uic.cpp:111
static bool isCppCommentChar(QChar c)
Definition uic.cpp:106