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
language.cpp
Go to the documentation of this file.
1// Copyright (C) 2018 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 "language.h"
5
6#include <QtCore/qtextstream.h>
7#include <QtCore/QList>
8
9#include <algorithm>
10
11namespace language {
12
13using namespace Qt::StringLiterals;
14
17
19
21{
22 _language = l;
23 switch (_language) {
24 case Language::Cpp:
25 derefPointer = u"->"_s;
26 listStart = '{';
27 listEnd = '}';
28 nullPtr = u"nullptr"_s;
29 operatorNew = u"new "_s;
30 qtQualifier = u"Qt::"_s;
31 qualifier = u"::"_s;
32 self = u""_s; // for testing: change to "this->";
33 eol = u";\n"_s;
34 emptyString = u"QString()"_s;
36 break;
37 case Language::Python:
38 derefPointer = u"."_s;
39 listStart = '[';
40 listEnd = ']';
41 nullPtr = u"None"_s;
42 operatorNew = u""_s;
43 qtQualifier = u"Qt."_s;
44 qualifier = u"."_s;
45 self = u"self."_s;
46 eol = u"\n"_s;
47 emptyString = u"\"\""_s;
49 break;
50 }
51}
52
63
65QString cppTrue = u"true"_s;
66QString cppFalse = u"false"_s;
67
68QTextStream &operator<<(QTextStream &str, const qtConfig &c)
69{
70 str << "QT_CONFIG(" << c.parameter() << ')';
71 return str;
72}
73
74QTextStream &operator<<(QTextStream &str, const openQtConfig &c)
75{
76 str << "#if " << qtConfig(c.parameter()) << '\n';
77 return str;
78}
79
80QTextStream &operator<<(QTextStream &str, const closeQtConfig &c)
81{
82 str << "#endif // " << qtConfig(c.parameter()) << '\n';
83 return str;
84}
85
91
92template <int N>
93QLatin1StringView lookupEnum(const EnumLookup(&array)[N], int value, int defaultIndex = 0)
94{
95 for (int i = 0; i < N; ++i) {
96 if (value == array[i].value)
97 return array[i].valueString;
98 }
99 auto defaultValue = array[defaultIndex].valueString;
100 qWarning("uic: Warning: Invalid enumeration value %d, defaulting to %s",
101 value, defaultValue.data());
102 return defaultValue;
103}
104
105QString fixClassName(QString className)
106{
107 switch (language()) {
108 case Language::Cpp:
109 className.replace(u'.', cppQualifier); // Nested Python class name
110 break;
111 case Language::Python:
112 className.replace(cppQualifier, "."_L1);
113 break;
114 }
115 return className;
116}
117
119{
120 static const EnumLookup toolBarAreas[] =
121 {
122 {0, "NoToolBarArea"_L1},
123 {0x1, "LeftToolBarArea"_L1},
124 {0x2, "RightToolBarArea"_L1},
125 {0x4, "TopToolBarArea"_L1},
126 {0x8, "BottomToolBarArea"_L1},
127 {0xf, "AllToolBarAreas"_L1}
128 };
129 return lookupEnum(toolBarAreas, v);
130}
131
133{
134 static const EnumLookup sizePolicies[] =
135 {
136 {0, "Fixed"_L1},
137 {0x1, "Minimum"_L1},
138 {0x4, "Maximum"_L1},
139 {0x5, "Preferred"_L1},
140 {0x3, "MinimumExpanding"_L1},
141 {0x7, "Expanding"_L1},
142 {0xD, "Ignored"_L1}
143 };
144 return lookupEnum(sizePolicies, v, 3);
145}
146
148{
149 static const EnumLookup dockWidgetAreas[] =
150 {
151 {0, "NoDockWidgetArea"_L1},
152 {0x1, "LeftDockWidgetArea"_L1},
153 {0x2, "RightDockWidgetArea"_L1},
154 {0x4, "TopDockWidgetArea"_L1},
155 {0x8, "BottomDockWidgetArea"_L1},
156 {0xf, "AllDockWidgetAreas"_L1}
157 };
158 return lookupEnum(dockWidgetAreas, v);
159}
160
162{
163 static const EnumLookup colorRoles[] =
164 {
165 {0, "WindowText"_L1},
166 {1, "Button"_L1},
167 {2, "Light"_L1},
168 {3, "Midlight"_L1},
169 {4, "Dark"_L1},
170 {5, "Mid"_L1},
171 {6, "Text"_L1},
172 {7, "BrightText"_L1},
173 {8, "ButtonText"_L1},
174 {9, "Base"_L1},
175 {10, "Window"_L1},
176 {11, "Shadow"_L1},
177 {12, "Highlight"_L1},
178 {13, "HighlightedText"_L1},
179 {14, "Link"_L1},
180 {15, "LinkVisited"_L1},
181 {16, "AlternateBase"_L1},
182 {17, "NoRole"_L1},
183 {18, "ToolTipBase"_L1},
184 {19, "ToolTipText"_L1},
185 {20, "PlaceholderText"_L1},
186 };
187 return lookupEnum(colorRoles, v);
188}
189
190// Helpers for formatting a character sequences
191
192// Format a special character like '\x0a'
194 char prefix = 0)
195{
196 int length = 1 + width;
197 str << '\\';
198 if (prefix) {
199 str << prefix;
200 ++length;
201 }
202 const auto oldPadChar = str.padChar();
203 const auto oldFieldWidth = str.fieldWidth();
204 const auto oldFieldAlignment = str.fieldAlignment();
205 const auto oldIntegerBase = str.integerBase();
206 str.setPadChar(u'0');
210 str << value;
215 return length;
216}
217
219{
220 int length = 0;
221 switch (value) {
222 case '\\':
223 str << "\\\\";
224 length += 2;
225 break;
226 case '\"':
227 str << "\\\"";
228 length += 2;
229 break;
230 case '\n':
231 str << "\\n\"\n\"";
232 length += 5;
233 break;
234 default:
235 break;
236 }
237 return length;
238}
239
240// Format a sequence of characters for C++ with special characters numerically
241// escaped (non-raw string literals), wrappped at maxSegmentSize. FormattingTraits
242// are used to transform characters into (unsigned) codes, which can be used
243// for either normal escapes or Unicode code points as used in Unicode literals.
244
245enum : int { maxSegmentSize = 1024 };
246
247
248static uint characterCode(char c)
249{
250 return uchar(c);
251}
252
253static uint characterCode(QChar c)
254{
255 return c.unicode();
256}
257
258static uint characterCode(uint c)
259{
260 return c;
261}
262
263template <class Iterator>
265 const QString &indent,
267 char escapePrefix = 0)
268{
269 str << '"';
270 int length = 0;
271 while (it != end) {
272 const auto code = characterCode(*it);
273 if (code >= 0x80) {
275 } else if (const int l = formatSpecialCharacter(str, code)) {
276 length += l;
277 } else if (code != '\r') {
278 str << char(code);
279 ++length;
280 }
281 ++it;
282 if (it != end && length > maxSegmentSize) {
283 str << "\"\n" << indent << indent << '"';
284 length = 0;
285 }
286 }
287 str << '"';
288}
289
290static bool isSurrogate(QChar c)
291{
292 return c.isSurrogate();
293}
294
295void _formatString(QTextStream &str, const QString &value, const QString &indent,
296 bool qString)
297{
298 switch (encoding) {
299 // Special characters as 3 digit octal escapes (u8"\303\234mlaut")
300 case Encoding::Utf8: {
301 if (qString && _language == Language::Cpp)
302 str << "QString::fromUtf8(";
303 const QByteArray utf8 = value.toUtf8();
305 if (qString && _language == Language::Cpp)
306 str << ')';
307 }
308 break;
309 // Special characters as 4 digit hex Unicode points (u8"\u00dcmlaut")
310 case Encoding::Unicode:
311 str << 'u'; // Python Unicode literal
313 const auto ucs4 = value.toUcs4();
314 formatStringSequence(str, ucs4.cbegin(), ucs4.cend(), indent, 16, 8, 'U');
315 } else {
317 }
318 break;
319 }
320}
321
322QTextStream &operator<<(QTextStream &str, const repeat &r)
323{
324 for (int i = 0; i < r.m_count; ++i)
325 str << r.m_char;
326 return str;
327}
328
329startFunctionDefinition1::startFunctionDefinition1(const char *name, const QString &parameterType,
330 const QString &parameterName,
331 const QString &indent,
332 const char *returnType) :
333 m_name(name), m_parameterType(parameterType), m_parameterName(parameterName),
334 m_indent(indent), m_return(returnType)
335{
336}
337
338QTextStream &operator<<(QTextStream &str, const startFunctionDefinition1 &f)
339{
340 switch (language()) {
341 case Language::Cpp:
342 str << (f.m_return ? f.m_return : "void") << ' ' << f.m_name << '('
343 << f.m_parameterType;
344 if (f.m_parameterType.cend()->isLetter())
345 str << ' ';
346 str << f.m_parameterName << ')' << '\n' << f.m_indent << "{\n";
347 break;
348 case Language::Python:
349 str << "def " << f.m_name << "(self, " << f.m_parameterName << "):\n";
350 break;
351 }
352 return str;
353}
354
355endFunctionDefinition::endFunctionDefinition(const char *name) : m_name(name)
356{
357}
358
359QTextStream &operator<<(QTextStream &str, const endFunctionDefinition &f)
360{
361 switch (language()) {
362 case Language::Cpp:
363 str << "} // " << f.m_name << "\n\n";
364 break;
365 case Language::Python:
366 str << "# " << f.m_name << "\n\n";
367 break;
368 }
369 return str;
370}
371
372void _formatStackVariable(QTextStream &str, const char *className, QStringView varName,
374{
375 switch (language()) {
376 case Language::Cpp:
377 str << className << ' ' << varName;
379 str << '(';
380 break;
381 case Language::Python:
382 str << varName << " = " << className << '(';
384 str << ')';
385 break;
386 }
387}
388
389enum class OverloadUse {
391 WhenAmbiguousOrEmpty, // Use overload if
392 // - signal/slot is ambiguous
393 // - argument list is empty (chance of connecting mismatching T against const T &)
395};
396
397// Format a member function for a signal slot connection
398static bool isConstRef(const QStringView &arg)
399{
400 return arg.startsWith(u'Q') && arg != "QPoint"_L1 && arg != "QSize"_L1;
401}
402
403static QString formatOverload(const QStringView &parameters)
404{
405 QString result = "qOverload<"_L1;
406 const auto args = QStringView{parameters}.split(u',');
407 for (qsizetype i = 0, size = args.size(); i < size; ++i) {
408 const auto &arg = args.at(i);
409 if (i > 0)
410 result += u',';
411 const bool constRef = isConstRef(arg);
412 if (constRef)
413 result += "const "_L1;
414 result += arg;
415 if (constRef)
416 result += u'&';
417 }
418 result += u'>';
419 return result;
420}
421
423{
424 const qsizetype parenPos = s.signature.indexOf(u'(');
425 Q_ASSERT(parenPos >= 0);
427
428 const auto parameters = QStringView{s.signature}.mid(parenPos + 1,
429 s.signature.size() - parenPos - 2);
430
432 bool withOverload = false; // just to silence the compiler
433
434 switch (useQOverload) {
435 case OverloadUse::Always:
436 withOverload = true;
437 break;
438 case OverloadUse::Never:
439 withOverload = false;
440 break;
443 break;
444 }
445
446 if (withOverload)
447 str << formatOverload(parameters) << '(';
448
449 str << '&' << s.className << "::" << functionName;
450
451 if (withOverload)
452 str << ')';
453}
454
456 const SignalSlot &sender,
457 const SignalSlot &receiver)
458{
459 str << "QObject::connect(" << sender.name << ", ";
461 str << ", " << receiver.name << ", ";
463 str << ')';
464}
465
467 const SignalSlot &sender,
468 const SignalSlot &receiver)
469{
470 str << "QObject::connect(" << sender.name << ", SIGNAL("<< sender.signature
471 << "), " << receiver.name << ", SLOT(" << receiver.signature << "))";
472}
473
474void formatConnection(QTextStream &str, const SignalSlot &sender, const SignalSlot &receiver,
476{
477 switch (language()) {
478 case Language::Cpp:
479 switch (connectionSyntax) {
482 break;
485 break;
486 }
487 break;
488 case Language::Python: {
489 const auto paren = sender.signature.indexOf(u'(');
491 str << sender.name << '.' << senderSignature.left(paren);
492 // Signals like "QAbstractButton::clicked(checked=false)" require
493 // the parameter if it is used.
495 const QStringView parameters =
497 if (!parameters.isEmpty() && !parameters.contains(u','))
498 str << "[\"" << parameters << "\"]";
499 }
500 str << ".connect(" << receiver.name << '.'
502 << ')';
503 }
504 break;
505 }
506}
507
509{
510 switch (language()) {
511 case Language::Cpp:
512 return v ? cppTrue : cppFalse;
513 case Language::Python:
514 return v ? QStringLiteral("True") : QStringLiteral("False");
515 }
516 Q_UNREACHABLE();
517}
518
519static inline QString dot() { return QStringLiteral("."); }
520
521QString enumValue(const QString &value)
522{
523 if (language() == Language::Cpp || !value.contains(cppQualifier))
524 return value;
525 QString fixed = value;
526 fixed.replace(cppQualifier, dot());
527 return fixed;
528}
529
530} // namespace language
endFunctionDefinition(const char *name)
Definition language.cpp:355
Language
Definition language.h:12
QString self
Definition language.cpp:60
static uint characterCode(QChar c)
Definition language.cpp:253
Language language()
Definition language.cpp:18
QString qtQualifier
Definition language.cpp:58
static void formatStringBasedConnection(QTextStream &str, const SignalSlot &sender, const SignalSlot &receiver)
Definition language.cpp:466
static bool isSurrogate(QChar c)
Definition language.cpp:290
static int formatEscapedNumber(QTextStream &str, uint value, int base, int width, char prefix=0)
Definition language.cpp:193
static bool isConstRef(const QStringView &arg)
Definition language.cpp:398
static int formatSpecialCharacter(QTextStream &str, ushort value)
Definition language.cpp:218
QLatin1StringView dockWidgetArea(int v)
Definition language.cpp:147
char listStart
Definition language.cpp:54
static void formatStringSequence(QTextStream &str, Iterator it, Iterator end, const QString &indent, int escapeIntegerBase, int escapeWidth, char escapePrefix=0)
Definition language.cpp:264
QString emptyString
Definition language.cpp:62
QString nullPtr
Definition language.cpp:56
QLatin1StringView paletteColorRole(int v)
Definition language.cpp:161
void setLanguage(Language)
Definition language.cpp:20
static QString formatOverload(const QStringView &parameters)
Definition language.cpp:403
QTextStream & operator<<(QTextStream &str, const startFunctionDefinition1 &f)
Definition language.cpp:338
static QString dot()
Definition language.cpp:519
QTextStream & operator<<(QTextStream &str, const endFunctionDefinition &f)
Definition language.cpp:359
QString eol
Definition language.cpp:61
char listEnd
Definition language.cpp:55
QString qualifier
Definition language.cpp:59
static void formatMemberFnPtr(QTextStream &str, const SignalSlot &s, OverloadUse useQOverload)
Definition language.cpp:422
QString cppFalse
Definition language.cpp:66
static void formatMemberFnPtrConnection(QTextStream &str, const SignalSlot &sender, const SignalSlot &receiver)
Definition language.cpp:455
static uint characterCode(char c)
Definition language.cpp:248
QString cppTrue
Definition language.cpp:65
QTextStream & operator<<(QTextStream &str, const repeat &r)
Definition language.cpp:322
static Language _language
Definition language.cpp:16
static uint characterCode(uint c)
Definition language.cpp:258
QString cppQualifier
Definition language.cpp:64
@ maxSegmentSize
Definition language.cpp:245
QLatin1StringView toolbarArea(int v)
Definition language.cpp:118
QString operatorNew
Definition language.cpp:57
QLatin1StringView sizePolicy(int v)
Definition language.cpp:132
QString derefPointer
Definition language.cpp:53
QLatin1StringView lookupEnum(const EnumLookup(&array)[N], int value, int defaultIndex=0)
Definition language.cpp:93
QString boolValue(bool v)
Definition language.cpp:508
static Encoding encoding
Definition language.cpp:15
QLatin1StringView valueString
Definition language.cpp:89