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
cppwriteinitialization.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
7#include "driver.h"
8#include "ui4.h"
9#include "utils.h"
10#include "uic.h"
11#include "databaseinfo.h"
12
13#include <language.h>
14
15#include <qtextstream.h>
16#include <qversionnumber.h>
17#include <qdebug.h>
18
19#include <algorithm>
20
22
23using namespace Qt::StringLiterals;
24
25namespace {
26
27 // Expand "Horizontal", "Qt::Horizontal" to "Qt::Orientation::Horizontal"
28 QString expandEnum(QString value, const QString &prefix)
29 {
30 if (value.startsWith(prefix))
31 return value;
32 const auto pos = value.lastIndexOf("::"_L1);
33 if (pos == -1)
34 return prefix + "::"_L1 + value;
35 value.replace(0, pos, prefix);
36 return value;
37 }
38
39 inline QString expandSizePolicyEnum(const QString &value)
40 {
41 return expandEnum(value, "QSizePolicy::Policy"_L1);
42 }
43
44 inline QString expandToolBarArea(const QString &value)
45 {
46 return expandEnum(value, "Qt::ToolBarArea"_L1);
47 }
48
49 inline QString expandDockWidgetArea(const QString &value)
50 {
51 return expandEnum(value, "Qt::DockWidgetArea"_L1);
52 }
53
54 // figure out the toolbar area of a DOM attrib list.
55 // By legacy, it is stored as an integer. As of 4.3.0, it is the enumeration value.
56 QString toolBarAreaStringFromDOMAttributes(const CPP::WriteInitialization::DomPropertyMap &attributes) {
57 const DomProperty *pstyle = attributes.value("toolBarArea"_L1);
58 QString result;
59 if (!pstyle)
60 return result;
61 switch (pstyle->kind()) {
62 case DomProperty::Number:
63 result = language::toolbarArea(pstyle->elementNumber());
64 break;
65 case DomProperty::Enum:
66 result = pstyle->elementEnum();
67 break;
68 default:
69 break;
70 }
71 return expandToolBarArea(result) + ", "_L1;
72 }
73
74 // Write a statement to create a spacer item.
75 void writeSpacerItem(const DomSpacer *node, QTextStream &output) {
76 const QHash<QString, DomProperty *> properties = propertyMap(node->elementProperty());
77 output << language::operatorNew << "QSpacerItem(";
78
79 int w = 0;
80 int h = 0;
81 if (const DomProperty *sh = properties.value("sizeHint"_L1)) {
82 if (const DomSize *sizeHint = sh->elementSize()) {
83 w = sizeHint->elementWidth();
84 h = sizeHint->elementHeight();
85 }
86 }
87 output << w << ", " << h << ", ";
88
89 // size type
90 const DomProperty *st = properties.value("sizeType"_L1);
91 QString horizType = st != nullptr ? st->elementEnum() : "Expanding"_L1;
92 QString vertType = "Minimum"_L1;
93
94 // orientation
95 const DomProperty *o = properties.value("orientation"_L1);
96 if (o != nullptr && o->elementEnum().endsWith("Vertical"_L1))
97 std::swap(horizType, vertType);
98
99 output << language::enumValue(expandSizePolicyEnum(horizType)) << ", "
100 << language::enumValue(expandSizePolicyEnum(vertType)) << ')';
101 }
102
103
104 // Helper for implementing comparison functions for integers.
105 int compareInt(int i1, int i2) {
106 if (i1 < i2) return -1;
107 if (i1 > i2) return 1;
108 return 0;
109 }
110
111 // Write object->setFoo(x);
112 template <class Value>
113 void writeSetter(const QString &indent, const QString &varName,const QString &setter, Value v, QTextStream &str) {
114 str << indent << varName << language::derefPointer
115 << setter << '(' << v << ')' << language::eol;
116 }
117
118 static inline bool iconHasStatePixmaps(const DomResourceIcon *i) {
119 return i->hasElementNormalOff() || i->hasElementNormalOn() ||
120 i->hasElementDisabledOff() || i->hasElementDisabledOn() ||
121 i->hasElementActiveOff() || i->hasElementActiveOn() ||
122 i->hasElementSelectedOff() || i->hasElementSelectedOn();
123 }
124
125 static inline bool isIconFormat44(const DomResourceIcon *i) {
126 return iconHasStatePixmaps(i) || !i->attributeTheme().isEmpty();
127 }
128
129 // Check on properties. Filter out empty legacy pixmap/icon properties
130 // as Designer pre 4.4 used to remove missing resource references.
131 // This can no longer be handled by the code as we have 'setIcon(QIcon())' as well as 'QIcon icon'
132 static bool checkProperty(const CustomWidgetsInfo *customWidgetsInfo,
133 const QString &fileName, const QString &className,
134 const DomProperty *p) {
135
136 const QString &name = p->attributeName();
137
138 switch (p->kind()) {
139 // ### fixme Qt 7 remove this: Exclude deprecated properties of Qt 5.
140 case DomProperty::Set:
141 if (name == u"features"
142 && customWidgetsInfo->extends(className, "QDockWidget")
143 && p->elementSet() == u"QDockWidget::AllDockWidgetFeatures") {
144 const QString msg = fileName + ": Warning: Deprecated enum value QDockWidget::AllDockWidgetFeatures was encountered."_L1;
145 qWarning("%s", qPrintable(msg));
146 return false;
147 }
148 break;
149 case DomProperty::Enum:
150 if (name == u"sizeAdjustPolicy"
151 && customWidgetsInfo->extends(className, "QComboBox")
152 && p->elementEnum() == u"QComboBox::AdjustToMinimumContentsLength") {
153 const QString msg = fileName + ": Warning: Deprecated enum value QComboBox::AdjustToMinimumContentsLength was encountered."_L1;
154 qWarning("%s", qPrintable(msg));
155 return false;
156 }
157 // Qt 7 separate layout size constraints (QTBUG-17730)
158 if (name == "verticalSizeConstraint"_L1 && className.contains("Layout"_L1))
159 return false;
160 break;
161 case DomProperty::IconSet:
162 if (const DomResourceIcon *dri = p->elementIconSet()) {
163 if (!isIconFormat44(dri)) {
164 if (dri->text().isEmpty()) {
165 const QString msg = "%1: Warning: An invalid icon property '%2' was encountered."_L1
166 .arg(fileName, name);
167 qWarning("%s", qPrintable(msg));
168 return false;
169 }
170 }
171 }
172 break;
173 case DomProperty::Pixmap:
174 if (const DomResourcePixmap *drp = p->elementPixmap())
175 if (drp->text().isEmpty()) {
176 const QString msg = "%1: Warning: An invalid pixmap property '%2' was encountered."_L1
177 .arg(fileName, name);
178 qWarning("%s", qPrintable(msg));
179 return false;
180 }
181 break;
182 default:
183 break;
184 }
185 return true;
186 }
187}
188
189// QtGui
190static inline QString accessibilityConfigKey() { return QStringLiteral("accessibility"); }
191static inline QString shortcutConfigKey() { return QStringLiteral("shortcut"); }
192static inline QString whatsThisConfigKey() { return QStringLiteral("whatsthis"); }
193// QtWidgets
194static inline QString statusTipConfigKey() { return QStringLiteral("statustip"); }
195static inline QString toolTipConfigKey() { return QStringLiteral("tooltip"); }
196
197namespace CPP {
198
199FontHandle::FontHandle(const DomFont *domFont) :
200 m_domFont(domFont)
201{
202}
203
204static QString fontWeight(const DomFont *domFont)
205{
206 if (domFont->hasElementFontWeight())
207 return domFont->elementFontWeight();
208 if (domFont->hasElementBold())
209 return domFont->elementBold() ? u"Bold"_s : u"Normal"_s;
210 return {};
211}
212
213int FontHandle::compare(const FontHandle &rhs) const
214{
215 const QString family = m_domFont->hasElementFamily() ? m_domFont->elementFamily() : QString();
216 const QString rhsFamily = rhs.m_domFont->hasElementFamily() ? rhs.m_domFont->elementFamily() : QString();
217
218 if (const int frc = family.compare(rhsFamily))
219 return frc;
220
221 const int pointSize = m_domFont->hasElementPointSize() ? m_domFont->elementPointSize() : -1;
222 const int rhsPointSize = rhs.m_domFont->hasElementPointSize() ? rhs.m_domFont->elementPointSize() : -1;
223
224 if (const int crc = compareInt(pointSize, rhsPointSize))
225 return crc;
226
227 const QString fontWeight = CPP::fontWeight(m_domFont);
228 const QString rhsFontWeight = CPP::fontWeight(rhs.m_domFont);
229 if (const int wrc = fontWeight.compare(rhsFontWeight))
230 return wrc;
231
232 const int italic = m_domFont->hasElementItalic() ? (m_domFont->elementItalic() ? 1 : 0) : -1;
233 const int rhsItalic = rhs.m_domFont->hasElementItalic() ? (rhs.m_domFont->elementItalic() ? 1 : 0) : -1;
234 if (const int crc = compareInt(italic, rhsItalic))
235 return crc;
236
237 const int underline = m_domFont->hasElementUnderline() ? (m_domFont->elementUnderline() ? 1 : 0) : -1;
238 const int rhsUnderline = rhs.m_domFont->hasElementUnderline() ? (rhs.m_domFont->elementUnderline() ? 1 : 0) : -1;
239 if (const int crc = compareInt(underline, rhsUnderline))
240 return crc;
241
242 const int strikeOut = m_domFont->hasElementStrikeOut() ? (m_domFont->elementStrikeOut() ? 1 : 0) : -1;
243 const int rhsStrikeOut = rhs.m_domFont->hasElementStrikeOut() ? (rhs.m_domFont->elementStrikeOut() ? 1 : 0) : -1;
244 if (const int crc = compareInt(strikeOut, rhsStrikeOut))
245 return crc;
246
247 const int kerning = m_domFont->hasElementKerning() ? (m_domFont->elementKerning() ? 1 : 0) : -1;
248 const int rhsKerning = rhs.m_domFont->hasElementKerning() ? (rhs.m_domFont->elementKerning() ? 1 : 0) : -1;
249 if (const int crc = compareInt(kerning, rhsKerning))
250 return crc;
251
252 const int antialiasing = m_domFont->hasElementAntialiasing() ? (m_domFont->elementAntialiasing() ? 1 : 0) : -1;
253 const int rhsAntialiasing = rhs.m_domFont->hasElementAntialiasing() ? (rhs.m_domFont->elementAntialiasing() ? 1 : 0) : -1;
254 if (const int crc = compareInt(antialiasing, rhsAntialiasing))
255 return crc;
256
257 const QString styleStrategy = m_domFont->hasElementStyleStrategy() ? m_domFont->elementStyleStrategy() : QString();
258 const QString rhsStyleStrategy = rhs.m_domFont->hasElementStyleStrategy() ? rhs.m_domFont->elementStyleStrategy() : QString();
259
260 if (const int src = styleStrategy.compare(rhsStyleStrategy))
261 return src;
262
263 const QString hintingPreference = m_domFont->hasElementHintingPreference()
264 ? m_domFont->elementHintingPreference() : QString();
265 const QString rhsHintingPreference = rhs.m_domFont->hasElementHintingPreference()
266 ? rhs.m_domFont->elementHintingPreference() : QString();
267 if (const int src = hintingPreference.compare(rhsHintingPreference))
268 return src;
269
270 return 0;
271}
272
273IconHandle::IconHandle(const DomResourceIcon *domIcon) :
274 m_domIcon(domIcon)
275{
276}
277
278int IconHandle::compare(const IconHandle &rhs) const
279{
280 if (const int comp = m_domIcon->attributeTheme().compare(rhs.m_domIcon->attributeTheme()))
281 return comp;
282
283 const QString normalOff = m_domIcon->hasElementNormalOff() ? m_domIcon->elementNormalOff()->text() : QString();
284 const QString rhsNormalOff = rhs.m_domIcon->hasElementNormalOff() ? rhs.m_domIcon->elementNormalOff()->text() : QString();
285 if (const int comp = normalOff.compare(rhsNormalOff))
286 return comp;
287
288 const QString normalOn = m_domIcon->hasElementNormalOn() ? m_domIcon->elementNormalOn()->text() : QString();
289 const QString rhsNormalOn = rhs.m_domIcon->hasElementNormalOn() ? rhs.m_domIcon->elementNormalOn()->text() : QString();
290 if (const int comp = normalOn.compare(rhsNormalOn))
291 return comp;
292
293 const QString disabledOff = m_domIcon->hasElementDisabledOff() ? m_domIcon->elementDisabledOff()->text() : QString();
294 const QString rhsDisabledOff = rhs.m_domIcon->hasElementDisabledOff() ? rhs.m_domIcon->elementDisabledOff()->text() : QString();
295 if (const int comp = disabledOff.compare(rhsDisabledOff))
296 return comp;
297
298 const QString disabledOn = m_domIcon->hasElementDisabledOn() ? m_domIcon->elementDisabledOn()->text() : QString();
299 const QString rhsDisabledOn = rhs.m_domIcon->hasElementDisabledOn() ? rhs.m_domIcon->elementDisabledOn()->text() : QString();
300 if (const int comp = disabledOn.compare(rhsDisabledOn))
301 return comp;
302
303 const QString activeOff = m_domIcon->hasElementActiveOff() ? m_domIcon->elementActiveOff()->text() : QString();
304 const QString rhsActiveOff = rhs.m_domIcon->hasElementActiveOff() ? rhs.m_domIcon->elementActiveOff()->text() : QString();
305 if (const int comp = activeOff.compare(rhsActiveOff))
306 return comp;
307
308 const QString activeOn = m_domIcon->hasElementActiveOn() ? m_domIcon->elementActiveOn()->text() : QString();
309 const QString rhsActiveOn = rhs.m_domIcon->hasElementActiveOn() ? rhs.m_domIcon->elementActiveOn()->text() : QString();
310 if (const int comp = activeOn.compare(rhsActiveOn))
311 return comp;
312
313 const QString selectedOff = m_domIcon->hasElementSelectedOff() ? m_domIcon->elementSelectedOff()->text() : QString();
314 const QString rhsSelectedOff = rhs.m_domIcon->hasElementSelectedOff() ? rhs.m_domIcon->elementSelectedOff()->text() : QString();
315 if (const int comp = selectedOff.compare(rhsSelectedOff))
316 return comp;
317
318 const QString selectedOn = m_domIcon->hasElementSelectedOn() ? m_domIcon->elementSelectedOn()->text() : QString();
319 const QString rhsSelectedOn = rhs.m_domIcon->hasElementSelectedOn() ? rhs.m_domIcon->elementSelectedOn()->text() : QString();
320 if (const int comp = selectedOn.compare(rhsSelectedOn))
321 return comp;
322 // Pre 4.4 Legacy
323 if (const int comp = m_domIcon->text().compare(rhs.m_domIcon->text()))
324 return comp;
325
326 return 0;
327}
328
329SizePolicyHandle::SizePolicyHandle(const DomSizePolicy *domSizePolicy) :
330 m_domSizePolicy(domSizePolicy)
331{
332}
333
335{
336
337 const int hSizeType = m_domSizePolicy->hasElementHSizeType() ? m_domSizePolicy->elementHSizeType() : -1;
338 const int rhsHSizeType = rhs.m_domSizePolicy->hasElementHSizeType() ? rhs.m_domSizePolicy->elementHSizeType() : -1;
339 if (const int crc = compareInt(hSizeType, rhsHSizeType))
340 return crc;
341
342 const int vSizeType = m_domSizePolicy->hasElementVSizeType() ? m_domSizePolicy->elementVSizeType() : -1;
343 const int rhsVSizeType = rhs.m_domSizePolicy->hasElementVSizeType() ? rhs.m_domSizePolicy->elementVSizeType() : -1;
344 if (const int crc = compareInt(vSizeType, rhsVSizeType))
345 return crc;
346
347 const int hStretch = m_domSizePolicy->hasElementHorStretch() ? m_domSizePolicy->elementHorStretch() : -1;
348 const int rhsHStretch = rhs.m_domSizePolicy->hasElementHorStretch() ? rhs.m_domSizePolicy->elementHorStretch() : -1;
349 if (const int crc = compareInt(hStretch, rhsHStretch))
350 return crc;
351
352 const int vStretch = m_domSizePolicy->hasElementVerStretch() ? m_domSizePolicy->elementVerStretch() : -1;
353 const int rhsVStretch = rhs.m_domSizePolicy->hasElementVerStretch() ? rhs.m_domSizePolicy->elementVerStretch() : -1;
354 if (const int crc = compareInt(vStretch, rhsVStretch))
355 return crc;
356
357 const QString attributeHSizeType = m_domSizePolicy->hasAttributeHSizeType() ? m_domSizePolicy->attributeHSizeType() : QString();
358 const QString rhsAttributeHSizeType = rhs.m_domSizePolicy->hasAttributeHSizeType() ? rhs.m_domSizePolicy->attributeHSizeType() : QString();
359
360 if (const int hrc = attributeHSizeType.compare(rhsAttributeHSizeType))
361 return hrc;
362
363 const QString attributeVSizeType = m_domSizePolicy->hasAttributeVSizeType() ? m_domSizePolicy->attributeVSizeType() : QString();
364 const QString rhsAttributeVSizeType = rhs.m_domSizePolicy->hasAttributeVSizeType() ? rhs.m_domSizePolicy->attributeVSizeType() : QString();
365
366 return attributeVSizeType.compare(rhsAttributeVSizeType);
367}
368
369// --- WriteInitialization: LayoutDefaultHandler
370
371WriteInitialization::LayoutDefaultHandler::LayoutDefaultHandler()
372{
373 std::fill_n(m_state, int(NumProperties), 0U);
374 std::fill_n(m_defaultValues, int(NumProperties), 0);
375}
376
377
378
379void WriteInitialization::LayoutDefaultHandler::acceptLayoutDefault(DomLayoutDefault *node)
380{
381 if (!node)
382 return;
383 if (node->hasAttributeMargin()) {
384 m_state[Margin] |= HasDefaultValue;
385 m_defaultValues[Margin] = node->attributeMargin();
386 }
387 if (node->hasAttributeSpacing()) {
388 m_state[Spacing] |= HasDefaultValue;
389 m_defaultValues[Spacing] = node->attributeSpacing();
390 }
391}
392
393void WriteInitialization::LayoutDefaultHandler::acceptLayoutFunction(DomLayoutFunction *node)
394{
395 if (!node)
396 return;
397 if (node->hasAttributeMargin()) {
398 m_state[Margin] |= HasDefaultFunction;
399 m_functions[Margin] = node->attributeMargin();
400 m_functions[Margin] += "()"_L1;
401 }
402 if (node->hasAttributeSpacing()) {
403 m_state[Spacing] |= HasDefaultFunction;
404 m_functions[Spacing] = node->attributeSpacing();
405 m_functions[Spacing] += "()"_L1;
406 }
407}
408
409static inline void writeContentsMargins(const QString &indent, const QString &objectName, int value, QTextStream &str)
410{
411 QString contentsMargins;
412 QTextStream(&contentsMargins) << value << ", " << value << ", " << value << ", " << value;
413 writeSetter(indent, objectName, "setContentsMargins"_L1, contentsMargins, str);
414 }
415
416void WriteInitialization::LayoutDefaultHandler::writeProperty(int p, const QString &indent, const QString &objectName,
417 const DomPropertyMap &properties, const QString &propertyName, const QString &setter,
418 int defaultStyleValue, bool suppressDefault, QTextStream &str) const
419{
420 // User value
421 if (const DomProperty *prop = properties.value(propertyName)) {
422 const int value = prop->elementNumber();
423 // Emulate the pre 4.3 behaviour: The value form default value was only used to determine
424 // the default value, layout properties were always written
425 const bool useLayoutFunctionPre43 = !suppressDefault && (m_state[p] == (HasDefaultFunction|HasDefaultValue)) && value == m_defaultValues[p];
426 if (!useLayoutFunctionPre43) {
427 bool ifndefMac = (!(m_state[p] & (HasDefaultFunction|HasDefaultValue))
428 && value == defaultStyleValue);
429 if (ifndefMac)
430 str << "#ifndef Q_OS_MACOS\n";
431 if (p == Margin) { // Use setContentsMargins for numeric values
432 writeContentsMargins(indent, objectName, value, str);
433 } else {
434 writeSetter(indent, objectName, setter, value, str);
435 }
436 if (ifndefMac)
437 str << "#endif\n";
438 return;
439 }
440 }
441 if (suppressDefault)
442 return;
443 // get default.
444 if (m_state[p] & HasDefaultFunction) {
445 // Do not use setContentsMargins to avoid repetitive evaluations.
446 writeSetter(indent, objectName, setter, m_functions[p], str);
447 return;
448 }
449 if (m_state[p] & HasDefaultValue) {
450 if (p == Margin) { // Use setContentsMargins for numeric values
451 writeContentsMargins(indent, objectName, m_defaultValues[p], str);
452 } else {
453 writeSetter(indent, objectName, setter, m_defaultValues[p], str);
454 }
455 }
456}
457
458
459void WriteInitialization::LayoutDefaultHandler::writeProperties(const QString &indent, const QString &varName,
460 const DomPropertyMap &properties, int marginType,
461 bool suppressMarginDefault,
462 QTextStream &str) const {
463 // Write out properties and ignore the ones found in
464 // subsequent writing of the property list.
465 int defaultSpacing = marginType == WriteInitialization::Use43UiFile ? -1 : 6;
466 writeProperty(Spacing, indent, varName, properties, "spacing"_L1, "setSpacing"_L1,
467 defaultSpacing, false, str);
468 // We use 9 as TopLevelMargin, since Designer seem to always use 9.
469 static const int layoutmargins[4] = {-1, 9, 9, 0};
470 writeProperty(Margin, indent, varName, properties, "margin"_L1, "setMargin"_L1,
471 layoutmargins[marginType], suppressMarginDefault, str);
472}
473
474template <class DomElement> // (DomString, DomStringList)
475static bool needsTranslation(const DomElement *element)
476{
477 if (!element)
478 return false;
479 return !element->hasAttributeNotr() || !toBool(element->attributeNotr());
480}
481
482// --- WriteInitialization
493
495{
496 m_actionGroupChain.push(nullptr);
497 m_widgetChain.push(nullptr);
498 m_layoutChain.push(nullptr);
499
500 if (node->hasAttributeConnectslotsbyname())
501 m_connectSlotsByName = node->attributeConnectslotsbyname();
502
503 if (auto *customSlots = node->elementSlots()) {
504 m_customSlots = customSlots->elementSlot();
505 m_customSignals = customSlots->elementSignal();
506 }
507
508 acceptLayoutDefault(node->elementLayoutDefault());
509 acceptLayoutFunction(node->elementLayoutFunction());
510
511 if (node->elementCustomWidgets())
512 TreeWalker::acceptCustomWidgets(node->elementCustomWidgets());
513
514 if (m_option.generateImplemetation)
515 m_output << "#include <" << m_driver->headerFileName() << ">\n\n";
516
517 m_stdsetdef = true;
518 if (node->hasAttributeStdSetDef())
519 m_stdsetdef = node->attributeStdSetDef();
520
521 const QString className = node->elementClass() + m_option.postfix;
522 m_generatedClass = className;
523
524 const QString varName = m_driver->findOrInsertWidget(node->elementWidget());
525 m_mainFormVarName = varName;
526
527 const QString widgetClassName = node->elementWidget()->attributeClass();
528
529 const QString parameterType = widgetClassName + " *"_L1;
530 m_output << m_option.indent
531 << language::startFunctionDefinition1("setupUi", parameterType, varName, m_option.indent);
532
533 const QStringList connections = m_uic->databaseInfo()->connections();
534 for (const auto &connection : connections) {
535 if (connection == "(default)"_L1)
536 continue;
537
538 const QString varConn = connection + "Connection"_L1;
539 m_output << m_indent << varConn << " = QSqlDatabase::database("
540 << language::charliteral(connection, m_dindent) << ")" << language::eol;
541 }
542
543 acceptWidget(node->elementWidget());
544
545 if (!m_buddies.empty())
546 m_output << language::openQtConfig(shortcutConfigKey());
547 for (const Buddy &b : std::as_const(m_buddies)) {
548 const QString buddyVarName = m_driver->widgetVariableName(b.buddyAttributeName);
549 if (buddyVarName.isEmpty()) {
550 fprintf(stderr, "%s: Warning: Buddy assignment: '%s' is not a valid widget.\n",
551 qPrintable(m_option.messagePrefix()),
552 qPrintable(b.buddyAttributeName));
553 continue;
554 }
555
556 m_output << m_indent << b.labelVarName << language::derefPointer
557 << "setBuddy(" << buddyVarName << ')' << language::eol;
558 }
559 if (!m_buddies.empty())
560 m_output << language::closeQtConfig(shortcutConfigKey());
561
562 if (node->elementTabStops())
563 acceptTabStops(node->elementTabStops());
564
565 if (!m_delayedActionInitialization.isEmpty())
566 m_output << "\n" << m_delayedActionInitialization;
567
568 m_output << "\n" << m_indent << language::self
569 << "retranslateUi(" << varName << ')' << language::eol;
570
571 if (node->elementConnections())
572 acceptConnections(node->elementConnections());
573
574 if (!m_delayedInitialization.isEmpty())
575 m_output << "\n" << m_delayedInitialization << "\n";
576
577 if (m_option.autoConnection && m_connectSlotsByName) {
578 m_output << "\n" << m_indent << "QMetaObject" << language::qualifier
579 << "connectSlotsByName(" << varName << ')' << language::eol;
580 }
581
582 m_output << m_option.indent << language::endFunctionDefinition("setupUi");
583
584 if (!m_mainFormUsedInRetranslateUi) {
586 // Mark varName as unused to avoid compiler warnings.
587 m_refreshInitialization += m_indent;
588 m_refreshInitialization += "(void)"_L1;
589 m_refreshInitialization += varName ;
590 m_refreshInitialization += language::eol;
592 // output a 'pass' to have an empty function
593 m_refreshInitialization += m_indent;
594 m_refreshInitialization += "pass"_L1;
595 m_refreshInitialization += language::eol;
596 }
597 }
598
599 m_output << m_option.indent
600 << language::startFunctionDefinition1("retranslateUi", parameterType, varName, m_option.indent)
601 << m_refreshInitialization
602 << m_option.indent << language::endFunctionDefinition("retranslateUi");
603
604 m_layoutChain.pop();
605 m_widgetChain.pop();
606 m_actionGroupChain.pop();
607}
608
609void WriteInitialization::addWizardPage(const QString &pageVarName, const DomWidget *page, const QString &parentWidget)
610{
611 /* If the node has a (free-format) string "pageId" attribute (which could
612 * an integer or an enumeration value), use setPage(), else addPage(). */
613 QString id;
614 const auto &attributes = page->elementAttribute();
615 if (!attributes.empty()) {
616 for (const DomProperty *p : attributes) {
617 if (p->attributeName() == "pageId"_L1) {
618 if (const DomString *ds = p->elementString())
619 id = ds->text();
620 break;
621 }
622 }
623 }
624 if (id.isEmpty()) {
625 m_output << m_indent << parentWidget << language::derefPointer
626 << "addPage(" << pageVarName << ')' << language::eol;
627 } else {
628 m_output << m_indent << parentWidget << language::derefPointer
629 << "setPage(" << id << ", " << pageVarName << ')' << language::eol;
630 }
631}
632
633void WriteInitialization::acceptWidget(DomWidget *node)
634{
635 m_layoutMarginType = m_widgetChain.size() == 1 ? TopLevelMargin : ChildMargin;
636 const QString className = node->attributeClass();
637 const QString varName = m_driver->findOrInsertWidget(node);
638
639 QString parentWidget;
640 QString parentClass;
641 if (m_widgetChain.top()) {
642 parentWidget = m_driver->findOrInsertWidget(m_widgetChain.top());
643 parentClass = m_widgetChain.top()->attributeClass();
644 }
645
646 const QString savedParentWidget = parentWidget;
647
648 if (m_uic->isContainer(parentClass))
649 parentWidget.clear();
650
651 const auto *cwi = m_uic->customWidgetsInfo();
652
653 if (m_widgetChain.size() != 1) {
654 m_output << m_indent << varName << " = " << language::operatorNew
655 << language::fixClassName(CustomWidgetsInfo::realClassName(className))
656 << '(' << parentWidget << ')' << language::eol;
657 }
658
659 parentWidget = savedParentWidget;
660
661
662 if (cwi->extends(className, "QComboBox")) {
663 initializeComboBox(node);
664 } else if (cwi->extends(className, "QListWidget")) {
665 initializeListWidget(node);
666 } else if (cwi->extends(className, "QTreeWidget")) {
667 initializeTreeWidget(node);
668 } else if (cwi->extends(className, "QTableWidget")) {
669 initializeTableWidget(node);
670 }
671
672 if (m_uic->isButton(className))
673 addButtonGroup(node, varName);
674
675 writeProperties(varName, className, node->elementProperty());
676
677 if (!parentWidget.isEmpty()
678 && cwi->extends(className, "QMenu")) {
679 initializeMenu(node, parentWidget);
680 }
681
682 if (node->elementLayout().isEmpty())
683 m_layoutChain.push(nullptr);
684
685 m_layoutWidget = false;
686 if (className == "QWidget"_L1 && !node->hasAttributeNative()) {
687 if (const DomWidget* parentWidget = m_widgetChain.top()) {
688 const QString parentClass = parentWidget->attributeClass();
689 if (parentClass != "QMainWindow"_L1
690 && !m_uic->customWidgetsInfo()->isCustomWidgetContainer(parentClass)
691 && !m_uic->isContainer(parentClass))
692 m_layoutWidget = true;
693 }
694 }
695 m_widgetChain.push(node);
696 m_layoutChain.push(nullptr);
698 m_layoutChain.pop();
699 m_widgetChain.pop();
700 m_layoutWidget = false;
701
702 const DomPropertyMap attributes = propertyMap(node->elementAttribute());
703
704 const QString pageDefaultString = u"Page"_s;
705
706 if (cwi->extends(parentClass, "QMainWindow")) {
707 if (cwi->extends(className, "QMenuBar")) {
708 m_output << m_indent << parentWidget << language::derefPointer
709 << "setMenuBar(" << varName << ')' << language::eol;
710 } else if (cwi->extends(className, "QToolBar")) {
711 m_output << m_indent << parentWidget << language::derefPointer << "addToolBar("
712 << language::enumValue(toolBarAreaStringFromDOMAttributes(attributes)) << varName
713 << ')' << language::eol;
714
715 if (const DomProperty *pbreak = attributes.value("toolBarBreak"_L1)) {
716 if (pbreak->elementBool() == "true"_L1) {
717 m_output << m_indent << parentWidget << language::derefPointer
718 << "insertToolBarBreak(" << varName << ')' << language::eol;
719 }
720 }
721
722 } else if (cwi->extends(className, "QDockWidget")) {
723 m_output << m_indent << parentWidget << language::derefPointer << "addDockWidget(";
724 if (DomProperty *pstyle = attributes.value("dockWidgetArea"_L1)) {
725 QString a = expandDockWidgetArea(language::dockWidgetArea(pstyle->elementNumber()));
726 m_output << language::enumValue(a) << ", ";
727 }
728 m_output << varName << ")" << language::eol;
729 } else if (m_uic->customWidgetsInfo()->extends(className, "QStatusBar")) {
730 m_output << m_indent << parentWidget << language::derefPointer
731 << "setStatusBar(" << varName << ')' << language::eol;
732 } else {
733 m_output << m_indent << parentWidget << language::derefPointer
734 << "setCentralWidget(" << varName << ')' << language::eol;
735 }
736 }
737
738 // Check for addPageMethod of a custom plugin first
739 QString addPageMethod = cwi->customWidgetAddPageMethod(parentClass);
740 if (addPageMethod.isEmpty())
741 addPageMethod = cwi->simpleContainerAddPageMethod(parentClass);
742 if (!addPageMethod.isEmpty()) {
743 m_output << m_indent << parentWidget << language::derefPointer
744 << addPageMethod << '(' << varName << ')' << language::eol;
745 } else if (m_uic->customWidgetsInfo()->extends(parentClass, "QWizard")) {
746 addWizardPage(varName, node, parentWidget);
747 } else if (m_uic->customWidgetsInfo()->extends(parentClass, "QToolBox")) {
748 const DomProperty *plabel = attributes.value("label"_L1);
749 DomString *plabelString = plabel ? plabel->elementString() : nullptr;
750 QString icon;
751 if (const DomProperty *picon = attributes.value("icon"_L1))
752 icon = ", "_L1 + iconCall(picon); // Side effect: Writes icon definition
753 m_output << m_indent << parentWidget << language::derefPointer << "addItem("
754 << varName << icon << ", " << noTrCall(plabelString, pageDefaultString)
755 << ')' << language::eol;
756
757 autoTrOutput(plabelString, pageDefaultString) << m_indent << parentWidget
758 << language::derefPointer << "setItemText(" << parentWidget
759 << language::derefPointer << "indexOf(" << varName << "), "
760 << autoTrCall(plabelString, pageDefaultString) << ')' << language::eol;
761
762 if (DomProperty *ptoolTip = attributes.value("toolTip"_L1)) {
763 autoTrOutput(ptoolTip->elementString())
764 << language::openQtConfig(toolTipConfigKey())
765 << m_indent << parentWidget << language::derefPointer << "setItemToolTip(" << parentWidget
766 << language::derefPointer << "indexOf(" << varName << "), "
767 << autoTrCall(ptoolTip->elementString()) << ')' << language::eol
768 << language::closeQtConfig(toolTipConfigKey());
769 }
770 } else if (m_uic->customWidgetsInfo()->extends(parentClass, "QTabWidget")) {
771 const DomProperty *ptitle = attributes.value("title"_L1);
772 DomString *ptitleString = ptitle ? ptitle->elementString() : nullptr;
773 QString icon;
774 if (const DomProperty *picon = attributes.value("icon"_L1))
775 icon = ", "_L1 + iconCall(picon); // Side effect: Writes icon definition
776 m_output << m_indent << parentWidget << language::derefPointer << "addTab("
777 << varName << icon << ", " << language::emptyString << ')' << language::eol;
778
779 autoTrOutput(ptitleString, pageDefaultString) << m_indent << parentWidget
780 << language::derefPointer << "setTabText(" << parentWidget
781 << language::derefPointer << "indexOf(" << varName << "), "
782 << autoTrCall(ptitleString, pageDefaultString) << ')' << language::eol;
783
784 if (const DomProperty *ptoolTip = attributes.value("toolTip"_L1)) {
785 autoTrOutput(ptoolTip->elementString())
786 << language::openQtConfig(toolTipConfigKey())
787 << m_indent << parentWidget << language::derefPointer << "setTabToolTip("
788 << parentWidget << language::derefPointer << "indexOf(" << varName
789 << "), " << autoTrCall(ptoolTip->elementString()) << ')' << language::eol
790 << language::closeQtConfig(toolTipConfigKey());
791 }
792 if (const DomProperty *pwhatsThis = attributes.value("whatsThis"_L1)) {
793 autoTrOutput(pwhatsThis->elementString())
794 << language::openQtConfig(whatsThisConfigKey())
795 << m_indent << parentWidget << language::derefPointer << "setTabWhatsThis("
796 << parentWidget << language::derefPointer << "indexOf(" << varName
797 << "), " << autoTrCall(pwhatsThis->elementString()) << ')' << language::eol
798 << language::closeQtConfig(whatsThisConfigKey());
799 }
800 }
801
802 //
803 // Special handling for qtableview/qtreeview fake header attributes
804 //
805 static const QLatin1StringView realPropertyNames[] = {
806 "visible"_L1,
807 "cascadingSectionResizes"_L1,
808 "minimumSectionSize"_L1, // before defaultSectionSize
809 "defaultSectionSize"_L1,
810 "highlightSections"_L1,
811 "showSortIndicator"_L1,
812 "stretchLastSection"_L1,
813 };
814
815 static const QStringList trees = {
816 u"QTreeView"_s, u"QTreeWidget"_s
817 };
818 static const QStringList tables = {
819 u"QTableView"_s, u"QTableWidget"_s
820 };
821
822 if (cwi->extendsOneOf(className, trees)) {
823 DomPropertyList headerProperties;
824 for (auto realPropertyName : realPropertyNames) {
825 const QString fakePropertyName = "header"_L1
826 + QChar(realPropertyName.at(0)).toUpper() + realPropertyName.mid(1);
827 if (DomProperty *fakeProperty = attributes.value(fakePropertyName)) {
828 fakeProperty->setAttributeName(realPropertyName);
829 headerProperties << fakeProperty;
830 }
831 }
832 writeProperties(varName + language::derefPointer + "header()"_L1,
833 "QHeaderView"_L1, headerProperties,
834 WritePropertyIgnoreObjectName);
835
836 } else if (cwi->extendsOneOf(className, tables)) {
837 static const QLatin1StringView headerPrefixes[] = {
838 "horizontalHeader"_L1,
839 "verticalHeader"_L1,
840 };
841
842 for (auto headerPrefix : headerPrefixes) {
843 DomPropertyList headerProperties;
844 for (auto realPropertyName : realPropertyNames) {
845 const QString fakePropertyName = headerPrefix
846 + QChar(realPropertyName.at(0)).toUpper() + realPropertyName.mid(1);
847 if (DomProperty *fakeProperty = attributes.value(fakePropertyName)) {
848 fakeProperty->setAttributeName(realPropertyName);
849 headerProperties << fakeProperty;
850 }
851 }
852 const QString headerVar = varName + language::derefPointer
853 + headerPrefix + "()"_L1;
854 writeProperties(headerVar, "QHeaderView"_L1,
855 headerProperties, WritePropertyIgnoreObjectName);
856 }
857 }
858
859 if (node->elementLayout().isEmpty())
860 m_layoutChain.pop();
861
862 const QStringList zOrder = node->elementZOrder();
863 for (const QString &name : zOrder) {
864 const QString varName = m_driver->widgetVariableName(name);
865 if (varName.isEmpty()) {
866 fprintf(stderr, "%s: Warning: Z-order assignment: '%s' is not a valid widget.\n",
867 qPrintable(m_option.messagePrefix()),
868 name.toLatin1().data());
869 } else {
870 m_output << m_indent << varName << language::derefPointer
871 << (language::language() != Language::Python ? "raise()" : "raise_()") << language::eol;
872 }
873 }
874}
875
876void WriteInitialization::addButtonGroup(const DomWidget *buttonNode, const QString &varName)
877{
878 const DomPropertyMap attributes = propertyMap(buttonNode->elementAttribute());
879 // Look up the button group name as specified in the attribute and find the uniquified name
880 const DomProperty *prop = attributes.value("buttonGroup"_L1);
881 if (!prop)
882 return;
883 const QString attributeName = toString(prop->elementString());
884 const DomButtonGroup *group = m_driver->findButtonGroup(attributeName);
885 // Legacy feature: Create missing groups on the fly as the UIC button group feature
886 // was present before the actual Designer support (4.5)
887 const bool createGroupOnTheFly = group == nullptr;
888 if (createGroupOnTheFly) {
889 auto *newGroup = new DomButtonGroup;
890 newGroup->setAttributeName(attributeName);
891 group = newGroup;
892 fprintf(stderr, "%s: Warning: Creating button group `%s'\n",
893 qPrintable(m_option.messagePrefix()),
894 attributeName.toLatin1().data());
895 }
896 const QString groupName = m_driver->findOrInsertButtonGroup(group);
897 // Create on demand
898 if (!m_buttonGroups.contains(groupName)) {
899 const QString className = u"QButtonGroup"_s;
900 m_output << m_indent;
901 if (createGroupOnTheFly)
902 m_output << className << " *";
903 m_output << groupName << " = " << language::operatorNew
904 << className << '(' << m_mainFormVarName << ')' << language::eol;
905 m_buttonGroups.insert(groupName);
906 writeProperties(groupName, className, group->elementProperty());
907 }
908 m_output << m_indent << groupName << language::derefPointer << "addButton("
909 << varName << ')' << language::eol;
910}
911
912void WriteInitialization::acceptLayout(DomLayout *node)
913{
914 const QString className = node->attributeClass();
915 const QString varName = m_driver->findOrInsertLayout(node);
916
917 const DomPropertyMap properties = propertyMap(node->elementProperty());
918 const bool oldLayoutProperties = properties.value("margin"_L1) != nullptr;
919
920 bool isGroupBox = false;
921
922 m_output << m_indent << varName << " = " << language::operatorNew << className << '(';
923
924 if (!m_layoutChain.top() && !isGroupBox)
925 m_output << m_driver->findOrInsertWidget(m_widgetChain.top());
926
927 m_output << ")" << language::eol;
928
929 // Suppress margin on a read child layout
930 const bool suppressMarginDefault = m_layoutChain.top();
931 int marginType = Use43UiFile;
932 if (oldLayoutProperties)
933 marginType = m_layoutMarginType;
934 m_LayoutDefaultHandler.writeProperties(m_indent, varName, properties, marginType, suppressMarginDefault, m_output);
935
936 m_layoutMarginType = SubLayoutMargin;
937
938 DomPropertyList propList = node->elementProperty();
939 DomPropertyList newPropList;
940 if (m_layoutWidget) {
941 bool left = false;
942 bool top = false;
943 bool right = false;
944 bool bottom = false;
945 for (const DomProperty *p : propList) {
946 const QString propertyName = p->attributeName();
947 if (propertyName == "leftMargin"_L1 && p->kind() == DomProperty::Number)
948 left = true;
949 else if (propertyName == "topMargin"_L1 && p->kind() == DomProperty::Number)
950 top = true;
951 else if (propertyName == "rightMargin"_L1 && p->kind() == DomProperty::Number)
952 right = true;
953 else if (propertyName == "bottomMargin"_L1 && p->kind() == DomProperty::Number)
954 bottom = true;
955 }
956 if (!left) {
957 auto *p = new DomProperty();
958 p->setAttributeName("leftMargin"_L1);
959 p->setElementNumber(0);
960 newPropList.append(p);
961 }
962 if (!top) {
963 auto *p = new DomProperty();
964 p->setAttributeName("topMargin"_L1);
965 p->setElementNumber(0);
966 newPropList.append(p);
967 }
968 if (!right) {
969 auto *p = new DomProperty();
970 p->setAttributeName("rightMargin"_L1);
971 p->setElementNumber(0);
972 newPropList.append(p);
973 }
974 if (!bottom) {
975 auto *p = new DomProperty();
976 p->setAttributeName("bottomMargin"_L1);
977 p->setElementNumber(0);
978 newPropList.append(p);
979 }
980 m_layoutWidget = false;
981 }
982
983 propList.append(newPropList);
984
985 writeProperties(varName, className, propList, WritePropertyIgnoreMargin|WritePropertyIgnoreSpacing);
986
987 // Clean up again:
988 propList.clear();
989 qDeleteAll(newPropList);
990 newPropList.clear();
991
992 m_layoutChain.push(node);
994 m_layoutChain.pop();
995
996 // Stretch? (Unless we are compiling for UIC3)
997 const QString numberNull(u'0');
998 writePropertyList(varName, "setStretch"_L1, node->attributeStretch(), numberNull);
999 writePropertyList(varName, "setRowStretch"_L1, node->attributeRowStretch(), numberNull);
1000 writePropertyList(varName, "setColumnStretch"_L1, node->attributeColumnStretch(), numberNull);
1001 writePropertyList(varName, "setColumnMinimumWidth"_L1, node->attributeColumnMinimumWidth(), numberNull);
1002 writePropertyList(varName, "setRowMinimumHeight"_L1, node->attributeRowMinimumHeight(), numberNull);
1003}
1004
1005// Apply a comma-separated list of values using a function "setSomething(int idx, value)"
1006void WriteInitialization::writePropertyList(const QString &varName,
1007 const QString &setFunction,
1008 const QString &value,
1009 const QString &defaultValue)
1010{
1011 if (value.isEmpty())
1012 return;
1013 const auto list = QStringView{value}.split(u',');
1014 for (qsizetype i = 0, count = list.size(); i < count; i++) {
1015 if (list.at(i) != defaultValue) {
1016 m_output << m_indent << varName << language::derefPointer << setFunction
1017 << '(' << i << ", " << list.at(i) << ')' << language::eol;
1018 }
1019 }
1020}
1021
1022void WriteInitialization::acceptSpacer(DomSpacer *node)
1023{
1024 m_output << m_indent << m_driver->findOrInsertSpacer(node) << " = ";
1025 writeSpacerItem(node, m_output);
1026 m_output << language::eol;
1027}
1028
1029static inline QString formLayoutRole(int column, int colspan)
1030{
1031 if (colspan > 1)
1032 return "QFormLayout::ItemRole::SpanningRole"_L1;
1033 return column == 0
1034 ? "QFormLayout::ItemRole::LabelRole"_L1 : "QFormLayout::ItemRole::FieldRole"_L1;
1035}
1036
1038{
1039 const auto methodPrefix = layoutClass == "QFormLayout"_L1 ? "set"_L1 : "add"_L1;
1040 switch (kind) {
1041 case DomLayoutItem::Widget:
1042 return methodPrefix + "Widget"_L1;
1043 case DomLayoutItem::Layout:
1044 return methodPrefix + "Layout"_L1;
1045 case DomLayoutItem::Spacer:
1046 return methodPrefix + "Item"_L1;
1047 case DomLayoutItem::Unknown:
1048 Q_ASSERT( false );
1049 break;
1050 }
1051 Q_UNREACHABLE();
1052}
1053
1054void WriteInitialization::acceptLayoutItem(DomLayoutItem *node)
1055{
1057
1058 DomLayout *layout = m_layoutChain.top();
1059
1060 if (!layout)
1061 return;
1062
1063 const QString layoutName = m_driver->findOrInsertLayout(layout);
1064 const QString itemName = m_driver->findOrInsertLayoutItem(node);
1065
1066 m_output << "\n" << m_indent << layoutName << language::derefPointer << ""
1067 << layoutAddMethod(node->kind(), layout->attributeClass()) << '(';
1068
1069 if (layout->attributeClass() == "QGridLayout"_L1) {
1070 const int row = node->attributeRow();
1071 const int col = node->attributeColumn();
1072
1073 const int rowSpan = node->hasAttributeRowSpan() ? node->attributeRowSpan() : 1;
1074 const int colSpan = node->hasAttributeColSpan() ? node->attributeColSpan() : 1;
1075 m_output << itemName << ", " << row << ", " << col << ", " << rowSpan << ", " << colSpan;
1076 if (!node->attributeAlignment().isEmpty())
1077 m_output << ", " << language::enumValue(node->attributeAlignment());
1078 } else if (layout->attributeClass() == "QFormLayout"_L1) {
1079 const int row = node->attributeRow();
1080 const int colSpan = node->hasAttributeColSpan() ? node->attributeColSpan() : 1;
1081 const QString role = formLayoutRole(node->attributeColumn(), colSpan);
1082 m_output << row << ", " << language::enumValue(role) << ", " << itemName;
1083 } else {
1084 m_output << itemName;
1085 if (layout->attributeClass().contains("Box"_L1) && !node->attributeAlignment().isEmpty())
1086 m_output << ", 0, " << language::enumValue(node->attributeAlignment());
1087 }
1088 m_output << ")" << language::eol << "\n";
1089}
1090
1091void WriteInitialization::acceptActionGroup(DomActionGroup *node)
1092{
1093 const QString actionName = m_driver->findOrInsertActionGroup(node);
1094 QString varName = m_driver->findOrInsertWidget(m_widgetChain.top());
1095
1096 if (m_actionGroupChain.top())
1097 varName = m_driver->findOrInsertActionGroup(m_actionGroupChain.top());
1098
1099 m_output << m_indent << actionName << " = " << language::operatorNew
1100 << "QActionGroup(" << varName << ")" << language::eol;
1101 writeProperties(actionName, "QActionGroup"_L1, node->elementProperty());
1102
1103 m_actionGroupChain.push(node);
1105 m_actionGroupChain.pop();
1106}
1107
1108void WriteInitialization::acceptAction(DomAction *node)
1109{
1110 if (node->hasAttributeMenu())
1111 return;
1112
1113 const QString actionName = m_driver->findOrInsertAction(node);
1114 QString varName = m_driver->findOrInsertWidget(m_widgetChain.top());
1115
1116 if (m_actionGroupChain.top())
1117 varName = m_driver->findOrInsertActionGroup(m_actionGroupChain.top());
1118
1119 m_output << m_indent << actionName << " = " << language::operatorNew
1120 << "QAction(" << varName << ')' << language::eol;
1121 writeProperties(actionName, "QAction"_L1, node->elementProperty());
1122}
1123
1124void WriteInitialization::acceptActionRef(DomActionRef *node)
1125{
1126 QString actionName = node->attributeName();
1127 if (actionName.isEmpty() || !m_widgetChain.top()
1128 || m_driver->actionGroupByName(actionName)) {
1129 return;
1130 }
1131
1132 const QString varName = m_driver->findOrInsertWidget(m_widgetChain.top());
1133
1134 if (m_widgetChain.top() && actionName == "separator"_L1) {
1135 // separator is always reserved!
1136 m_actionOut << m_indent << varName << language::derefPointer
1137 << "addSeparator()" << language::eol;
1138 return;
1139 }
1140
1141 const DomWidget *domWidget = m_driver->widgetByName(actionName);
1142 if (domWidget && m_uic->isMenu(domWidget->attributeClass())) {
1143 m_actionOut << m_indent << varName << language::derefPointer
1144 << "addAction(" << m_driver->findOrInsertWidget(domWidget)
1145 << language::derefPointer << "menuAction())" << language::eol;
1146 return;
1147 }
1148
1149 const DomAction *domAction = m_driver->actionByName(actionName);
1150 if (!domAction) {
1151 fprintf(stderr, "%s: Warning: action `%s' not declared\n",
1152 qPrintable(m_option.messagePrefix()), qPrintable(actionName));
1153 return;
1154 }
1155
1156 m_actionOut << m_indent << varName << language::derefPointer
1157 << "addAction(" << m_driver->findOrInsertAction(domAction)
1158 << ')' << language::eol;
1159}
1160
1161QString WriteInitialization::writeStringListProperty(const DomStringList *list) const
1162{
1163 QString propertyValue;
1164 QTextStream str(&propertyValue);
1165 char trailingDelimiter = '}';
1166 switch (language::language()) {
1167 case Language::Cpp:
1168 str << "QStringList{";
1169 break;
1170 case Language::Python:
1171 str << '[';
1172 trailingDelimiter = ']';
1173 break;
1174 }
1175 const QStringList values = list->elementString();
1176 if (!values.isEmpty()) {
1177 if (needsTranslation(list)) {
1178 const QString comment = list->attributeComment();
1179 const qsizetype last = values.size() - 1;
1180 for (qsizetype i = 0; i <= last; ++i) {
1181 str << '\n' << m_indent << " " << trCall(values.at(i), comment);
1182 if (i != last)
1183 str << ',';
1184 }
1185 } else {
1186 for (qsizetype i = 0; i < values.size(); ++i) {
1187 if (i)
1188 str << ", ";
1189 str << language::qstring(values.at(i), m_dindent);
1190 }
1191 }
1192 }
1193 str << trailingDelimiter;
1194 return propertyValue;
1195}
1196
1197static QString configKeyForProperty(const QString &propertyName)
1198{
1199 if (propertyName == "toolTip"_L1)
1200 return toolTipConfigKey();
1201 if (propertyName == "whatsThis"_L1)
1202 return whatsThisConfigKey();
1203 if (propertyName == "statusTip"_L1)
1204 return statusTipConfigKey();
1205 if (propertyName == "shortcut"_L1)
1206 return shortcutConfigKey();
1207 if (propertyName == "accessibleName"_L1 || propertyName == "accessibleDescription"_L1)
1208 return accessibilityConfigKey();
1209 return {};
1210}
1211
1212void WriteInitialization::writeProperties(const QString &varName,
1213 const QString &className,
1214 const DomPropertyList &lst,
1215 unsigned flags)
1216{
1217 const bool isTopLevel = m_widgetChain.size() == 1;
1218
1219 if (m_uic->customWidgetsInfo()->extends(className, "QAxWidget")) {
1220 DomPropertyMap properties = propertyMap(lst);
1221 if (DomProperty *p = properties.value("control"_L1)) {
1222 m_output << m_indent << varName << language::derefPointer << "setControl("
1223 << language::qstring(toString(p->elementString()), m_dindent)
1224 << ')' << language::eol;
1225 }
1226 }
1227
1228 QString indent;
1229 if (!m_widgetChain.top()) {
1230 indent = m_option.indent;
1231 switch (language::language()) {
1232 case Language::Cpp:
1233 m_output << m_indent << "if (" << varName << "->objectName().isEmpty())\n";
1234 break;
1235 case Language::Python:
1236 m_output << m_indent << "if not " << varName << ".objectName():\n";
1237 break;
1238 }
1239 }
1240 if (!(flags & WritePropertyIgnoreObjectName)) {
1241 QString objectName = varName;
1242 if (!language::self.isEmpty() && objectName.startsWith(language::self))
1243 objectName.remove(0, language::self.size());
1244 m_output << m_indent << indent
1245 << varName << language::derefPointer << "setObjectName("
1246 << language::charliteral(objectName, m_dindent) << ')' << language::eol;
1247 }
1248
1249 int leftMargin = -1;
1250 int topMargin = -1;
1251 int rightMargin = -1;
1252 int bottomMargin = -1;
1253 bool frameShadowEncountered = false;
1254
1255 for (const DomProperty *p : lst) {
1256 if (!checkProperty(m_uic->customWidgetsInfo(), m_option.inputFile, className, p))
1257 continue;
1258 QString propertyName = p->attributeName();
1259 // Qt 7 separate layout size constraints (QTBUG-17730)
1260 if (propertyName == "horizontalSizeConstraint"_L1 && className.contains("Layout"_L1))
1261 propertyName = "sizeConstraint"_L1;
1262 QString propertyValue;
1263 bool delayProperty = false;
1264
1265 // special case for the property `geometry': Do not use position
1266 if (isTopLevel && propertyName == "geometry"_L1 && p->elementRect()) {
1267 const DomRect *r = p->elementRect();
1268 m_output << m_indent << varName << language::derefPointer << "resize("
1269 << r->elementWidth() << ", " << r->elementHeight() << ')' << language::eol;
1270 continue;
1271 }
1272 if (propertyName == "currentRow"_L1 // QListWidget::currentRow
1273 && m_uic->customWidgetsInfo()->extends(className, "QListWidget")) {
1274 m_delayedOut << m_indent << varName << language::derefPointer
1275 << "setCurrentRow(" << p->elementNumber() << ')' << language::eol;
1276 continue;
1277 }
1278 static const QStringList currentIndexWidgets = {
1279 u"QComboBox"_s, u"QStackedWidget"_s,
1280 u"QTabWidget"_s, u"QToolBox"_s
1281 };
1282 if (propertyName == "currentIndex"_L1 // set currentIndex later
1283 && (m_uic->customWidgetsInfo()->extendsOneOf(className, currentIndexWidgets))) {
1284 m_delayedOut << m_indent << varName << language::derefPointer
1285 << "setCurrentIndex(" << p->elementNumber() << ')' << language::eol;
1286 continue;
1287 }
1288 if (propertyName == "tabSpacing"_L1
1289 && m_uic->customWidgetsInfo()->extends(className, "QToolBox")) {
1290 m_delayedOut << m_indent << varName << language::derefPointer
1291 << "layout()" << language::derefPointer << "setSpacing("
1292 << p->elementNumber() << ')' << language::eol;
1293 continue;
1294 }
1295 if (propertyName == "control"_L1 // ActiveQt support
1296 && m_uic->customWidgetsInfo()->extends(className, "QAxWidget")) {
1297 // already done ;)
1298 continue;
1299 }
1300 if (propertyName == "default"_L1
1301 && m_uic->customWidgetsInfo()->extends(className, "QPushButton")) {
1302 // QTBUG-44406: Setting of QPushButton::default needs to be delayed until the parent is set
1303 delayProperty = true;
1304 } else if (propertyName == "database"_L1
1305 && p->elementStringList()) {
1306 // Sql support
1307 continue;
1308 } else if (propertyName == "frameworkCode"_L1
1309 && p->kind() == DomProperty::Bool) {
1310 // Sql support
1311 continue;
1312 } else if (propertyName == "orientation"_L1
1313 && m_uic->customWidgetsInfo()->extends(className, "Line")) {
1314 // Line support
1315 QString shape = u"QFrame::Shape::HLine"_s;
1316 if (p->elementEnum().endsWith("::Vertical"_L1))
1317 shape = u"QFrame::Shape::VLine"_s;
1318
1319 m_output << m_indent << varName << language::derefPointer << "setFrameShape("
1320 << language::enumValue(shape) << ')' << language::eol;
1321 // QFrame Default is 'Plain'. Make the line 'Sunken' unless otherwise specified
1322 if (!frameShadowEncountered) {
1323 m_output << m_indent << varName << language::derefPointer
1324 << "setFrameShadow("
1325 << language::enumValue("QFrame::Shadow::Sunken"_L1)
1326 << ')' << language::eol;
1327 }
1328 continue;
1329 } else if ((flags & WritePropertyIgnoreMargin) && propertyName == "margin"_L1) {
1330 continue;
1331 } else if ((flags & WritePropertyIgnoreSpacing) && propertyName == "spacing"_L1) {
1332 continue;
1333 } else if (propertyName == "leftMargin"_L1 && p->kind() == DomProperty::Number) {
1334 leftMargin = p->elementNumber();
1335 continue;
1336 } else if (propertyName == "topMargin"_L1 && p->kind() == DomProperty::Number) {
1337 topMargin = p->elementNumber();
1338 continue;
1339 } else if (propertyName == "rightMargin"_L1 && p->kind() == DomProperty::Number) {
1340 rightMargin = p->elementNumber();
1341 continue;
1342 } else if (propertyName == "bottomMargin"_L1 && p->kind() == DomProperty::Number) {
1343 bottomMargin = p->elementNumber();
1344 continue;
1345 } else if (propertyName == "numDigits"_L1 // Deprecated in Qt 4, removed in Qt 5.
1346 && m_uic->customWidgetsInfo()->extends(className, "QLCDNumber")) {
1347 qWarning("Widget '%s': Deprecated property QLCDNumber::numDigits encountered. It has been replaced by QLCDNumber::digitCount.",
1348 qPrintable(varName));
1349 propertyName = "digitCount"_L1;
1350 } else if (propertyName == "frameShadow"_L1) {
1351 frameShadowEncountered = true;
1352 }
1353
1354 bool stdset = m_stdsetdef;
1355 if (p->hasAttributeStdset())
1356 stdset = p->attributeStdset();
1357
1358 QString setFunction;
1359
1360 {
1361 QTextStream str(&setFunction);
1362 if (stdset) {
1363 str << language::derefPointer <<"set" << propertyName.at(0).toUpper()
1364 << QStringView{propertyName}.mid(1) << '(';
1365 } else {
1366 str << language::derefPointer << "setProperty("_L1
1367 << language::charliteral(propertyName) << ", ";
1368 if (language::language() == Language::Cpp) {
1369 str << "QVariant";
1370 if (p->kind() == DomProperty::Enum)
1371 str << "::fromValue";
1372 str << '(';
1373 }
1374 }
1375 } // QTextStream
1376
1377 QString varNewName = varName;
1378
1379 switch (p->kind()) {
1380 case DomProperty::Bool: {
1381 propertyValue = language::boolValue(p->elementBool() == language::cppTrue);
1382 break;
1383 }
1384 case DomProperty::Color:
1385 propertyValue = domColor2QString(p->elementColor());
1386 break;
1387 case DomProperty::Cstring:
1388 if (propertyName == "buddy"_L1 && m_uic->customWidgetsInfo()->extends(className, "QLabel")) {
1389 Buddy buddy = { varName, p->elementCstring() };
1390 m_buddies.append(std::move(buddy));
1391 } else {
1392 const bool useQByteArray = !stdset && language::language() == Language::Cpp;
1393 QTextStream str(&propertyValue);
1394 if (useQByteArray)
1395 str << "QByteArray(";
1396 str << language::charliteral(p->elementCstring(), m_dindent);
1397 if (useQByteArray)
1398 str << ')';
1399 }
1400 break;
1401 case DomProperty::Cursor:
1402 propertyValue = QString::fromLatin1("QCursor(static_cast<Qt::CursorShape>(%1))")
1403 .arg(p->elementCursor());
1404 break;
1405 case DomProperty::CursorShape:
1406 if (p->hasAttributeStdset() && !p->attributeStdset())
1407 varNewName += language::derefPointer + "viewport()"_L1;
1408 propertyValue = "QCursor(Qt"_L1 + language::qualifier + "CursorShape"_L1
1409 + language::qualifier + p->elementCursorShape() + u')';
1410 break;
1411 case DomProperty::Enum:
1412 propertyValue = p->elementEnum();
1413 if (propertyValue.contains(language::cppQualifier))
1414 propertyValue = language::enumValue(propertyValue);
1415 else
1416 propertyValue.prepend(className + language::qualifier);
1417 break;
1418 case DomProperty::Set:
1419 propertyValue = language::enumValue(p->elementSet());
1420 break;
1421 case DomProperty::Font:
1422 propertyValue = writeFontProperties(p->elementFont());
1423 break;
1424 case DomProperty::IconSet:
1425 propertyValue = writeIconProperties(p->elementIconSet());
1426 break;
1427 case DomProperty::Pixmap:
1428 propertyValue = pixCall(p);
1429 break;
1430 case DomProperty::Palette: {
1431 const DomPalette *pal = p->elementPalette();
1432 const QString paletteName = m_driver->unique("palette"_L1);
1433 m_output << m_indent << language::stackVariable("QPalette", paletteName)
1434 << language::eol;
1435 writeColorGroup(pal->elementActive(),
1436 "QPalette::ColorGroup::Active"_L1, paletteName);
1437 writeColorGroup(pal->elementInactive(),
1438 "QPalette::ColorGroup::Inactive"_L1, paletteName);
1439 writeColorGroup(pal->elementDisabled(),
1440 "QPalette::ColorGroup::Disabled"_L1, paletteName);
1441
1442 propertyValue = paletteName;
1443 break;
1444 }
1445 case DomProperty::Point: {
1446 const DomPoint *po = p->elementPoint();
1447 propertyValue = QString::fromLatin1("QPoint(%1, %2)")
1448 .arg(po->elementX()).arg(po->elementY());
1449 break;
1450 }
1451 case DomProperty::PointF: {
1452 const DomPointF *pof = p->elementPointF();
1453 propertyValue = QString::fromLatin1("QPointF(%1, %2)")
1454 .arg(pof->elementX()).arg(pof->elementY());
1455 break;
1456 }
1457 case DomProperty::Rect: {
1458 const DomRect *r = p->elementRect();
1459 propertyValue = QString::fromLatin1("QRect(%1, %2, %3, %4)")
1460 .arg(r->elementX()).arg(r->elementY())
1461 .arg(r->elementWidth()).arg(r->elementHeight());
1462 break;
1463 }
1464 case DomProperty::RectF: {
1465 const DomRectF *rf = p->elementRectF();
1466 propertyValue = QString::fromLatin1("QRectF(%1, %2, %3, %4)")
1467 .arg(rf->elementX()).arg(rf->elementY())
1468 .arg(rf->elementWidth()).arg(rf->elementHeight());
1469 break;
1470 }
1471 case DomProperty::Locale: {
1472 const DomLocale *locale = p->elementLocale();
1473 QTextStream(&propertyValue) << "QLocale(QLocale" << language::qualifier
1474 << locale->attributeLanguage() << ", QLocale" << language::qualifier
1475 << locale->attributeCountry() << ')';
1476 break;
1477 }
1478 case DomProperty::SizePolicy: {
1479 const QString spName = writeSizePolicy( p->elementSizePolicy());
1480 m_output << m_indent << spName << ".setHeightForWidth("
1481 << varName << language::derefPointer << "sizePolicy().hasHeightForWidth())"
1482 << language::eol;
1483
1484 propertyValue = spName;
1485 break;
1486 }
1487 case DomProperty::Size: {
1488 const DomSize *s = p->elementSize();
1489 propertyValue = QString::fromLatin1("QSize(%1, %2)")
1490 .arg(s->elementWidth()).arg(s->elementHeight());
1491 break;
1492 }
1493 case DomProperty::SizeF: {
1494 const DomSizeF *sf = p->elementSizeF();
1495 propertyValue = QString::fromLatin1("QSizeF(%1, %2)")
1496 .arg(sf->elementWidth()).arg(sf->elementHeight());
1497 break;
1498 }
1499 case DomProperty::String: {
1500 if (propertyName == "objectName"_L1) {
1501 const QString v = p->elementString()->text();
1502 if (v == varName)
1503 break;
1504
1505 // ### qWarning("Deprecated: the property `objectName' is different from the variable name");
1506 }
1507
1508 propertyValue = autoTrCall(p->elementString());
1509 break;
1510 }
1511 case DomProperty::Number:
1512 propertyValue = QString::number(p->elementNumber());
1513 break;
1514 case DomProperty::UInt:
1515 propertyValue = QString::number(p->elementUInt());
1516 propertyValue += u'u';
1517 break;
1518 case DomProperty::LongLong:
1519 propertyValue = "Q_INT64_C("_L1;
1520 propertyValue += QString::number(p->elementLongLong());
1521 propertyValue += u')';
1522 break;
1523 case DomProperty::ULongLong:
1524 propertyValue = "Q_UINT64_C("_L1;
1525 propertyValue += QString::number(p->elementULongLong());
1526 propertyValue += u')';
1527 break;
1528 case DomProperty::Float:
1529 propertyValue = QString::number(p->elementFloat(), 'f', 8);
1530 break;
1531 case DomProperty::Double:
1532 propertyValue = QString::number(p->elementDouble(), 'f', 15);
1533 break;
1534 case DomProperty::Char: {
1535 const DomChar *c = p->elementChar();
1536 propertyValue = QString::fromLatin1("QChar(%1)")
1537 .arg(c->elementUnicode());
1538 break;
1539 }
1540 case DomProperty::Date: {
1541 const DomDate *d = p->elementDate();
1542 propertyValue = QString::fromLatin1("QDate(%1, %2, %3)")
1543 .arg(d->elementYear())
1544 .arg(d->elementMonth())
1545 .arg(d->elementDay());
1546 break;
1547 }
1548 case DomProperty::Time: {
1549 const DomTime *t = p->elementTime();
1550 propertyValue = QString::fromLatin1("QTime(%1, %2, %3)")
1551 .arg(t->elementHour())
1552 .arg(t->elementMinute())
1553 .arg(t->elementSecond());
1554 break;
1555 }
1556 case DomProperty::DateTime: {
1557 const DomDateTime *dt = p->elementDateTime();
1558 propertyValue = QString::fromLatin1("QDateTime(QDate(%1, %2, %3), QTime(%4, %5, %6))")
1559 .arg(dt->elementYear())
1560 .arg(dt->elementMonth())
1561 .arg(dt->elementDay())
1562 .arg(dt->elementHour())
1563 .arg(dt->elementMinute())
1564 .arg(dt->elementSecond());
1565 break;
1566 }
1567 case DomProperty::StringList:
1568 propertyValue = writeStringListProperty(p->elementStringList());
1569 break;
1570
1571 case DomProperty::Url: {
1572 const DomUrl* u = p->elementUrl();
1573 QTextStream(&propertyValue) << "QUrl("
1574 << language::qstring(u->elementString()->text(), m_dindent) << ")";
1575 break;
1576 }
1577 case DomProperty::Brush:
1578 propertyValue = writeBrushInitialization(p->elementBrush());
1579 break;
1580 case DomProperty::Unknown:
1581 break;
1582 }
1583
1584 if (!propertyValue.isEmpty()) {
1585 const QString configKey = configKeyForProperty(propertyName);
1586
1587 QTextStream &o = delayProperty ? m_delayedOut : autoTrOutput(p);
1588
1589 if (!configKey.isEmpty())
1590 o << language::openQtConfig(configKey);
1591 o << m_indent << varNewName << setFunction << propertyValue;
1592 if (!stdset && language::language() == Language::Cpp)
1593 o << ')';
1594 o << ')' << language::eol;
1595 if (!configKey.isEmpty())
1596 o << language::closeQtConfig(configKey);
1597
1598 if (varName == m_mainFormVarName && &o == &m_refreshOut) {
1599 // this is the only place (currently) where we output mainForm name to the retranslateUi().
1600 // Other places output merely instances of a certain class (which cannot be main form, e.g. QListWidget).
1601 m_mainFormUsedInRetranslateUi = true;
1602 }
1603 }
1604 }
1605 if (leftMargin != -1 || topMargin != -1 || rightMargin != -1 || bottomMargin != -1) {
1606 m_output << m_indent << varName << language::derefPointer << "setContentsMargins("
1607 << leftMargin << ", " << topMargin << ", "
1608 << rightMargin << ", " << bottomMargin << ")" << language::eol;
1609 }
1610}
1611
1612QString WriteInitialization::writeSizePolicy(const DomSizePolicy *sp)
1613{
1614
1615 // check cache
1616 const SizePolicyHandle sizePolicyHandle(sp);
1617 const SizePolicyNameMap::const_iterator it = m_sizePolicyNameMap.constFind(sizePolicyHandle);
1618 if ( it != m_sizePolicyNameMap.constEnd()) {
1619 return it.value();
1620 }
1621
1622
1623 // insert with new name
1624 const QString spName = m_driver->unique("sizePolicy"_L1);
1625 m_sizePolicyNameMap.insert(sizePolicyHandle, spName);
1626
1627 m_output << m_indent << language::stackVariableWithInitParameters("QSizePolicy", spName);
1628 QString horizPolicy;
1629 QString vertPolicy;
1630 if (sp->hasElementHSizeType() && sp->hasElementVSizeType()) {
1631 horizPolicy = language::sizePolicy(sp->elementHSizeType());
1632 vertPolicy = language::sizePolicy(sp->elementVSizeType());
1633 } else if (sp->hasAttributeHSizeType() && sp->hasAttributeVSizeType()) {
1634 horizPolicy = sp->attributeHSizeType();
1635 vertPolicy = sp->attributeVSizeType();
1636 }
1637 if (!horizPolicy.isEmpty() && !vertPolicy.isEmpty()) {
1638 m_output << language::enumValue(expandSizePolicyEnum(horizPolicy))
1639 << ", " << language::enumValue(expandSizePolicyEnum(vertPolicy));
1640 }
1641 m_output << ')' << language::eol;
1642
1643 m_output << m_indent << spName << ".setHorizontalStretch("
1644 << sp->elementHorStretch() << ")" << language::eol;
1645 m_output << m_indent << spName << ".setVerticalStretch("
1646 << sp->elementVerStretch() << ")" << language::eol;
1647 return spName;
1648}
1649// Check for a font with the given properties in the FontPropertiesNameMap
1650// or create a new one. Returns the name.
1651
1652QString WriteInitialization::writeFontProperties(const DomFont *f)
1653{
1654 // check cache
1655 const FontHandle fontHandle(f);
1656 const FontPropertiesNameMap::const_iterator it = m_fontPropertiesNameMap.constFind(fontHandle);
1657 if ( it != m_fontPropertiesNameMap.constEnd()) {
1658 return it.value();
1659 }
1660
1661 // insert with new name
1662 const QString fontName = m_driver->unique("font"_L1);
1663 m_fontPropertiesNameMap.insert(FontHandle(f), fontName);
1664
1665 m_output << m_indent << language::stackVariable("QFont", fontName)
1666 << language::eol;
1667 if (f->hasElementFamily() && !f->elementFamily().isEmpty()) {
1668 m_output << m_indent << fontName << ".setFamilies("
1669 << language::listStart
1670 << language::qstring(f->elementFamily(), m_dindent)
1671 << language::listEnd << ')' << language::eol;
1672 }
1673 if (f->hasElementPointSize() && f->elementPointSize() > 0) {
1674 m_output << m_indent << fontName << ".setPointSize(" << f->elementPointSize()
1675 << ")" << language::eol;
1676 }
1677
1678 if (f->hasElementFontWeight()) {
1679 m_output << m_indent << fontName << ".setWeight(QFont"
1680 << language::qualifier << f->elementFontWeight() << ')' << language::eol;
1681 } else if (f->hasElementBold()) {
1682 m_output << m_indent << fontName << ".setBold("
1683 << language::boolValue(f->elementBold()) << ')' << language::eol;
1684 }
1685
1686 if (f->hasElementItalic()) {
1687 m_output << m_indent << fontName << ".setItalic("
1688 << language::boolValue(f->elementItalic()) << ')' << language::eol;
1689 }
1690 if (f->hasElementUnderline()) {
1691 m_output << m_indent << fontName << ".setUnderline("
1692 << language::boolValue(f->elementUnderline()) << ')' << language::eol;
1693 }
1694 if (f->hasElementStrikeOut()) {
1695 m_output << m_indent << fontName << ".setStrikeOut("
1696 << language::boolValue(f->elementStrikeOut()) << ')' << language::eol;
1697 }
1698 if (f->hasElementKerning()) {
1699 m_output << m_indent << fontName << ".setKerning("
1700 << language::boolValue(f->elementKerning()) << ')' << language::eol;
1701 }
1702 if (f->hasElementAntialiasing()) {
1703 m_output << m_indent << fontName << ".setStyleStrategy(QFont"
1704 << language::qualifier
1705 << (f->elementAntialiasing() ? "PreferDefault" : "NoAntialias")
1706 << ')' << language::eol;
1707 }
1708 if (f->hasElementStyleStrategy()) {
1709 m_output << m_indent << fontName << ".setStyleStrategy(QFont"
1710 << language::qualifier << f->elementStyleStrategy() << ')' << language::eol;
1711 }
1712 if (f->hasElementHintingPreference()) {
1713 m_output << m_indent << fontName << ".setHintingPreference(QFont"
1714 << language::qualifier << f->elementHintingPreference() << ')' << language::eol;
1715 }
1716
1717 return fontName;
1718}
1719
1720static void writeIconAddFile(QTextStream &output, const QString &indent,
1721 const QString &iconName, const QString &fileName,
1722 const char *mode, const char *state)
1723{
1724 output << indent << iconName << ".addFile("
1725 << language::qstring(fileName, indent) << ", QSize(), QIcon"
1726 << language::qualifier << "Mode" << language::qualifier << mode
1727 << ", QIcon" << language::qualifier << "State" << language::qualifier << state
1728 << ')' << language::eol;
1729}
1730
1731// Post 4.4 write resource icon
1732static void writeResourceIcon(QTextStream &output,
1733 const QString &iconName,
1734 const QString &indent,
1735 const DomResourceIcon *i)
1736{
1737 if (i->hasElementNormalOff()) {
1738 writeIconAddFile(output, indent, iconName, i->elementNormalOff()->text(),
1739 "Normal", "Off");
1740 }
1741 if (i->hasElementNormalOn()) {
1742 writeIconAddFile(output, indent, iconName, i->elementNormalOn()->text(),
1743 "Normal", "On");
1744 }
1745 if (i->hasElementDisabledOff()) {
1746 writeIconAddFile(output, indent, iconName, i->elementDisabledOff()->text(),
1747 "Disabled", "Off");
1748 }
1749 if (i->hasElementDisabledOn()) {
1750 writeIconAddFile(output, indent, iconName, i->elementDisabledOn()->text(),
1751 "Disabled", "On");
1752 }
1753 if (i->hasElementActiveOff()) {
1754 writeIconAddFile(output, indent, iconName, i->elementActiveOff()->text(),
1755 "Active", "Off");
1756 }
1757 if (i->hasElementActiveOn()) {
1758 writeIconAddFile(output, indent, iconName, i->elementActiveOn()->text(),
1759 "Active", "On");
1760 }
1761 if (i->hasElementSelectedOff()) {
1762 writeIconAddFile(output, indent, iconName, i->elementSelectedOff()->text(),
1763 "Selected", "Off");
1764 }
1765 if (i->hasElementSelectedOn()) {
1766 writeIconAddFile(output, indent, iconName, i->elementSelectedOn()->text(),
1767 "Selected", "On");
1768 }
1769}
1770
1771static void writeIconAddPixmap(QTextStream &output, const QString &indent,
1772 const QString &iconName, const QString &call,
1773 const char *mode, const char *state)
1774{
1775 output << indent << iconName << ".addPixmap(" << call << ", QIcon"
1776 << language::qualifier << "Mode" << language::qualifier << mode
1777 << ", QIcon" << language::qualifier << "State" << language::qualifier
1778 << state << ')' << language::eol;
1779}
1780
1781void WriteInitialization::writePixmapFunctionIcon(QTextStream &output,
1782 const QString &iconName,
1783 const QString &indent,
1784 const DomResourceIcon *i) const
1785{
1786 if (i->hasElementNormalOff()) {
1787 writeIconAddPixmap(output, indent, iconName,
1788 pixCall("QPixmap"_L1, i->elementNormalOff()->text()),
1789 "Normal", "Off");
1790 }
1791 if (i->hasElementNormalOn()) {
1792 writeIconAddPixmap(output, indent, iconName,
1793 pixCall("QPixmap"_L1, i->elementNormalOn()->text()),
1794 "Normal", "On");
1795 }
1796 if (i->hasElementDisabledOff()) {
1797 writeIconAddPixmap(output, indent, iconName,
1798 pixCall("QPixmap"_L1, i->elementDisabledOff()->text()),
1799 "Disabled", "Off");
1800 }
1801 if (i->hasElementDisabledOn()) {
1802 writeIconAddPixmap(output, indent, iconName,
1803 pixCall("QPixmap"_L1, i->elementDisabledOn()->text()),
1804 "Disabled", "On");
1805 }
1806 if (i->hasElementActiveOff()) {
1807 writeIconAddPixmap(output, indent, iconName,
1808 pixCall("QPixmap"_L1, i->elementActiveOff()->text()),
1809 "Active", "Off");
1810 }
1811 if (i->hasElementActiveOn()) {
1812 writeIconAddPixmap(output, indent, iconName,
1813 pixCall("QPixmap"_L1, i->elementActiveOn()->text()),
1814 "Active", "On");
1815 }
1816 if (i->hasElementSelectedOff()) {
1817 writeIconAddPixmap(output, indent, iconName,
1818 pixCall("QPixmap"_L1, i->elementSelectedOff()->text()),
1819 "Selected", "Off");
1820 }
1821 if (i->hasElementSelectedOn()) {
1822 writeIconAddPixmap(output, indent, iconName,
1823 pixCall("QPixmap"_L1, i->elementSelectedOn()->text()),
1824 "Selected", "On");
1825 }
1826}
1827
1828// Write QIcon::fromTheme() (value from enum or variable)
1830{
1831 explicit iconFromTheme(const QString &theme) : m_theme(theme) {}
1832
1833 QString m_theme;
1834};
1835
1836QTextStream &operator<<(QTextStream &str, const iconFromTheme &i)
1837{
1838 str << "QIcon" << language::qualifier << "fromTheme(" << i.m_theme << ')';
1839 return str;
1840}
1841
1842// Write QIcon::fromTheme() for an XDG icon from string literal
1844{
1845 explicit iconFromThemeStringLiteral(const QString &theme) : m_theme(theme) {}
1846
1847 QString m_theme;
1848};
1849
1850QTextStream &operator<<(QTextStream &str, const iconFromThemeStringLiteral &i)
1851{
1852 str << "QIcon" << language::qualifier << "fromTheme(" << language::qstring(i.m_theme) << ')';
1853 return str;
1854}
1855
1856// Write QIcon::fromTheme() with a path as fallback, add a check using
1857// QIcon::hasThemeIcon().
1858void WriteInitialization::writeThemeIconCheckAssignment(const QString &themeValue,
1859 const QString &iconName,
1860 const DomResourceIcon *i)
1861
1862{
1863 const bool isCpp = language::language() == Language::Cpp;
1864 m_output << m_indent << "if ";
1865 if (isCpp)
1866 m_output << '(';
1867 m_output << "QIcon" << language::qualifier << "hasThemeIcon("
1868 << themeValue << ')' << (isCpp ? ") {" : ":") << '\n'
1869 << m_dindent << iconName << " = " << iconFromTheme(themeValue)
1870 << language::eol;
1871 m_output << m_indent << (isCpp ? "} else {" : "else:") << '\n';
1872 if (m_uic->pixmapFunction().isEmpty())
1873 writeResourceIcon(m_output, iconName, m_dindent, i);
1874 else
1875 writePixmapFunctionIcon(m_output, iconName, m_dindent, i);
1876 if (isCpp)
1877 m_output << m_indent << '}';
1878 m_output << '\n';
1879}
1880
1881QString WriteInitialization::writeIconProperties(const DomResourceIcon *i)
1882{
1883 // check cache
1884 const IconHandle iconHandle(i);
1885 const IconPropertiesNameMap::const_iterator it = m_iconPropertiesNameMap.constFind(iconHandle);
1886 if (it != m_iconPropertiesNameMap.constEnd())
1887 return it.value();
1888
1889 // insert with new name
1890 const QString iconName = m_driver->unique("icon"_L1);
1891 m_iconPropertiesNameMap.insert(IconHandle(i), iconName);
1892
1893 const bool isCpp = language::language() == Language::Cpp;
1894
1895 if (Q_UNLIKELY(!isIconFormat44(i))) { // pre-4.4 legacy
1896 m_output << m_indent;
1897 if (isCpp)
1898 m_output << "const QIcon ";
1899 m_output << iconName << " = " << pixCall("QIcon"_L1, i->text())
1900 << language::eol;
1901 return iconName;
1902 }
1903
1904 // 4.4 onwards
1905 QString theme = i->attributeTheme();
1906 if (theme.isEmpty()) {
1907 // No theme: Write resource icon as is
1908 m_output << m_indent << language::stackVariable("QIcon", iconName)
1909 << language::eol;
1910 if (m_uic->pixmapFunction().isEmpty())
1911 writeResourceIcon(m_output, iconName, m_indent, i);
1912 else
1913 writePixmapFunctionIcon(m_output, iconName, m_indent, i);
1914 return iconName;
1915 }
1916
1917 const bool isThemeEnum = theme.startsWith("QIcon::"_L1);
1918 if (isThemeEnum)
1919 theme = language::enumValue(theme);
1920
1921 // Theme: Generate code to check the theme and default to resource
1922 if (iconHasStatePixmaps(i)) {
1923 // Theme + default state pixmaps:
1924 // Generate code to check the theme and default to state pixmaps
1925 m_output << m_indent << language::stackVariable("QIcon", iconName) << language::eol;
1926 if (isThemeEnum) {
1927 writeThemeIconCheckAssignment(theme, iconName, i);
1928 return iconName;
1929 }
1930
1931 static constexpr auto themeNameStringVariableC = "iconThemeName"_L1;
1932 // Store theme name in a variable
1933 m_output << m_indent;
1934 if (m_firstThemeIcon) { // Declare variable string
1935 if (isCpp)
1936 m_output << "QString ";
1937 m_firstThemeIcon = false;
1938 }
1939 m_output << themeNameStringVariableC << " = "
1940 << language::qstring(theme) << language::eol;
1941 writeThemeIconCheckAssignment(themeNameStringVariableC, iconName, i);
1942 return iconName;
1943 }
1944
1945 // Theme, but no state pixmaps: Construct from theme directly.
1946 m_output << m_indent
1947 << language::stackVariableWithInitParameters("QIcon", iconName);
1948 if (isThemeEnum)
1949 m_output << iconFromTheme(theme);
1950 else
1951 m_output << iconFromThemeStringLiteral(theme);
1952 m_output << ')' << language::eol;
1953 return iconName;
1954}
1955
1956QString WriteInitialization::domColor2QString(const DomColor *c)
1957{
1958 if (c->hasAttributeAlpha())
1959 return QString::fromLatin1("QColor(%1, %2, %3, %4)")
1960 .arg(c->elementRed())
1961 .arg(c->elementGreen())
1962 .arg(c->elementBlue())
1963 .arg(c->attributeAlpha());
1964 return QString::fromLatin1("QColor(%1, %2, %3)")
1965 .arg(c->elementRed())
1966 .arg(c->elementGreen())
1967 .arg(c->elementBlue());
1968}
1969
1970static inline QVersionNumber colorRoleVersionAdded(const QString &roleName)
1971{
1972 if (roleName == "PlaceholderText"_L1)
1973 return {5, 12, 0};
1974 if (roleName == "Accent"_L1)
1975 return {6, 6, 0};
1976 return {};
1977}
1978
1979void WriteInitialization::writeColorGroup(DomColorGroup *colorGroup, const QString &group, const QString &paletteName)
1980{
1981 if (!colorGroup)
1982 return;
1983
1984 // old format
1985 const auto &colors = colorGroup->elementColor();
1986 for (int i=0; i<colors.size(); ++i) {
1987 const DomColor *color = colors.at(i);
1988
1989 m_output << m_indent << paletteName << ".setColor(" << group
1990 << ", QPalette" << language::qualifier << "ColorRole"
1991 << language::qualifier << language::paletteColorRole(i)
1992 << ", " << domColor2QString(color)
1993 << ")" << language::eol;
1994 }
1995
1996 // new format
1997 const auto &colorRoles = colorGroup->elementColorRole();
1998 for (const DomColorRole *colorRole : colorRoles) {
1999 if (colorRole->hasAttributeRole()) {
2000 const QString roleName = colorRole->attributeRole();
2001 const QVersionNumber versionAdded = colorRoleVersionAdded(roleName);
2002 const QString brushName = writeBrushInitialization(colorRole->elementBrush());
2003 if (!versionAdded.isNull()) {
2004 m_output << "#if QT_VERSION >= QT_VERSION_CHECK("
2005 << versionAdded.majorVersion() << ", " << versionAdded.minorVersion()
2006 << ", " << versionAdded.microVersion() << ")\n";
2007 }
2008 m_output << m_indent << paletteName << ".setBrush("
2009 << language::enumValue(group) << ", "
2010 << "QPalette" << language::qualifier << "ColorRole"
2011 << language::qualifier << roleName << ", " << brushName << ')' << language::eol;
2012 if (!versionAdded.isNull())
2013 m_output << "#endif\n";
2014 }
2015 }
2016}
2017
2018// Write initialization for brush unless it is found in the cache. Returns the name to use
2019// in an expression.
2020QString WriteInitialization::writeBrushInitialization(const DomBrush *brush)
2021{
2022 // Simple solid, colored brushes are cached
2023 const bool solidColoredBrush = !brush->hasAttributeBrushStyle() || brush->attributeBrushStyle() == "SolidPattern"_L1;
2024 uint rgb = 0;
2025 if (solidColoredBrush) {
2026 if (const DomColor *color = brush->elementColor()) {
2027 rgb = ((color->elementRed() & 0xFF) << 24) |
2028 ((color->elementGreen() & 0xFF) << 16) |
2029 ((color->elementBlue() & 0xFF) << 8) |
2030 ((color->attributeAlpha() & 0xFF));
2031 const ColorBrushHash::const_iterator cit = m_colorBrushHash.constFind(rgb);
2032 if (cit != m_colorBrushHash.constEnd())
2033 return cit.value();
2034 }
2035 }
2036 // Create and enter into cache if simple
2037 const QString brushName = m_driver->unique("brush"_L1);
2038 writeBrush(brush, brushName);
2039 if (solidColoredBrush)
2040 m_colorBrushHash.insert(rgb, brushName);
2041 return brushName;
2042}
2043
2044void WriteInitialization::writeBrush(const DomBrush *brush, const QString &brushName)
2045{
2046 QString style = u"SolidPattern"_s;
2047 if (brush->hasAttributeBrushStyle())
2048 style = brush->attributeBrushStyle();
2049
2050 if (style == "LinearGradientPattern"_L1 ||
2051 style == "RadialGradientPattern"_L1 ||
2052 style == "ConicalGradientPattern"_L1) {
2053 const DomGradient *gradient = brush->elementGradient();
2054 const QString gradientType = gradient->attributeType();
2055 const QString gradientName = m_driver->unique("gradient"_L1);
2056 if (gradientType == "LinearGradient"_L1) {
2057 m_output << m_indent
2058 << language::stackVariableWithInitParameters("QLinearGradient", gradientName)
2059 << gradient->attributeStartX()
2060 << ", " << gradient->attributeStartY()
2061 << ", " << gradient->attributeEndX()
2062 << ", " << gradient->attributeEndY() << ')' << language::eol;
2063 } else if (gradientType == "RadialGradient"_L1) {
2064 m_output << m_indent
2065 << language::stackVariableWithInitParameters("QRadialGradient", gradientName)
2066 << gradient->attributeCentralX()
2067 << ", " << gradient->attributeCentralY()
2068 << ", " << gradient->attributeRadius()
2069 << ", " << gradient->attributeFocalX()
2070 << ", " << gradient->attributeFocalY() << ')' << language::eol;
2071 } else if (gradientType == "ConicalGradient"_L1) {
2072 m_output << m_indent
2073 << language::stackVariableWithInitParameters("QConicalGradient", gradientName)
2074 << gradient->attributeCentralX()
2075 << ", " << gradient->attributeCentralY()
2076 << ", " << gradient->attributeAngle() << ')' << language::eol;
2077 }
2078
2079 m_output << m_indent << gradientName << ".setSpread(QGradient"
2080 << language::qualifier << "Spread" << language::qualifier << gradient->attributeSpread()
2081 << ')' << language::eol;
2082
2083 if (gradient->hasAttributeCoordinateMode()) {
2084 m_output << m_indent << gradientName << ".setCoordinateMode(QGradient"
2085 << language::qualifier << "CoordinateMode" << language::qualifier
2086 << gradient->attributeCoordinateMode() << ')' << language::eol;
2087 }
2088
2089 const auto &stops = gradient->elementGradientStop();
2090 for (const DomGradientStop *stop : stops) {
2091 const DomColor *color = stop->elementColor();
2092 m_output << m_indent << gradientName << ".setColorAt("
2093 << stop->attributePosition() << ", "
2094 << domColor2QString(color) << ')' << language::eol;
2095 }
2096 m_output << m_indent
2097 << language::stackVariableWithInitParameters("QBrush", brushName)
2098 << gradientName << ')' << language::eol;
2099 } else if (style == "TexturePattern"_L1) {
2100 const DomProperty *property = brush->elementTexture();
2101 const QString iconValue = iconCall(property);
2102
2103 m_output << m_indent
2104 << language::stackVariableWithInitParameters("QBrush", brushName)
2105 << iconValue << ')' << language::eol;
2106 } else {
2107 const DomColor *color = brush->elementColor();
2108 m_output << m_indent
2109 << language::stackVariableWithInitParameters("QBrush", brushName)
2110 << domColor2QString(color) << ')' << language::eol;
2111
2112 m_output << m_indent << brushName << ".setStyle("
2113 << language::qtQualifier << "BrushStyle" << language::qualifier
2114 << style << ')' << language::eol;
2115 }
2116}
2117
2118void WriteInitialization::acceptCustomWidget(DomCustomWidget *node)
2119{
2120 Q_UNUSED(node);
2121}
2122
2123void WriteInitialization::acceptCustomWidgets(DomCustomWidgets *node)
2124{
2125 Q_UNUSED(node);
2126}
2127
2128void WriteInitialization::acceptTabStops(DomTabStops *tabStops)
2129{
2130 QString lastName;
2131
2132 const QStringList l = tabStops->elementTabStop();
2133 for (int i=0; i<l.size(); ++i) {
2134 const QString name = m_driver->widgetVariableName(l.at(i));
2135
2136 if (name.isEmpty()) {
2137 fprintf(stderr, "%s: Warning: Tab-stop assignment: '%s' is not a valid widget.\n",
2138 qPrintable(m_option.messagePrefix()), qPrintable(l.at(i)));
2139 continue;
2140 }
2141
2142 if (i == 0) {
2143 lastName = name;
2144 continue;
2145 }
2146 if (name.isEmpty() || lastName.isEmpty())
2147 continue;
2148
2149 m_output << m_indent << "QWidget" << language::qualifier << "setTabOrder("
2150 << lastName << ", " << name << ')' << language::eol;
2151
2152 lastName = name;
2153 }
2154}
2155
2156QString WriteInitialization::iconCall(const DomProperty *icon)
2157{
2158 if (icon->kind() == DomProperty::IconSet)
2159 return writeIconProperties(icon->elementIconSet());
2160 return pixCall(icon);
2161}
2162
2163QString WriteInitialization::pixCall(const DomProperty *p) const
2164{
2165 QLatin1StringView type;
2166 QString s;
2167 switch (p->kind()) {
2168 case DomProperty::IconSet:
2169 type = "QIcon"_L1;
2170 s = p->elementIconSet()->text();
2171 break;
2172 case DomProperty::Pixmap:
2173 type = "QPixmap"_L1;
2174 s = p->elementPixmap()->text();
2175 break;
2176 default:
2177 qWarning("%s: Warning: Unknown icon format encountered. The ui-file was generated with a too-recent version of Qt Widgets Designer.",
2178 qPrintable(m_option.messagePrefix()));
2179 return "QIcon()"_L1;
2180 break;
2181 }
2182 return pixCall(type, s);
2183}
2184
2185QString WriteInitialization::pixCall(QLatin1StringView t, const QString &text) const
2186{
2187 if (text.isEmpty())
2188 return t % "()"_L1;
2189
2190 QString result;
2191 QTextStream str(&result);
2192 str << t;
2193 str << '(';
2194 const QString pixFunc = m_uic->pixmapFunction();
2195 if (pixFunc.isEmpty())
2196 str << language::qstring(text, m_dindent);
2197 else
2198 str << pixFunc << '(' << language::charliteral(text, m_dindent) << ')';
2199 str << ')';
2200 return result;
2201}
2202
2203void WriteInitialization::initializeComboBox(DomWidget *w)
2204{
2205 const QString varName = m_driver->findOrInsertWidget(w);
2206
2207 const auto &items = w->elementItem();
2208
2209 if (items.isEmpty())
2210 return;
2211
2212 for (int i = 0; i < items.size(); ++i) {
2213 const DomItem *item = items.at(i);
2214 const DomPropertyMap properties = propertyMap(item->elementProperty());
2215 const DomProperty *text = properties.value("text"_L1);
2216 const DomProperty *icon = properties.value("icon"_L1);
2217
2218 QString iconValue;
2219 if (icon)
2220 iconValue = iconCall(icon);
2221
2222 m_output << m_indent << varName << language::derefPointer << "addItem(";
2223 if (icon)
2224 m_output << iconValue << ", ";
2225
2226 if (needsTranslation(text->elementString())) {
2227 m_output << language::emptyString << ')' << language::eol;
2228 m_refreshOut << m_indent << varName << language::derefPointer
2229 << "setItemText(" << i << ", " << trCall(text->elementString())
2230 << ')' << language::eol;
2231 } else {
2232 m_output << noTrCall(text->elementString()) << ")" << language::eol;
2233 }
2234 }
2235 m_refreshOut << "\n";
2236}
2237
2238QString WriteInitialization::disableSorting(DomWidget *w, const QString &varName)
2239{
2240 // turn off sortingEnabled to force programmatic item order (setItem())
2241 QString tempName;
2242 if (!w->elementItem().isEmpty()) {
2243 tempName = m_driver->unique("__sortingEnabled"_L1);
2244 m_refreshOut << "\n";
2245 m_refreshOut << m_indent;
2246 if (language::language() == Language::Cpp)
2247 m_refreshOut << "const bool ";
2248 m_refreshOut << tempName << " = " << varName << language::derefPointer
2249 << "isSortingEnabled()" << language::eol
2250 << m_indent << varName << language::derefPointer
2251 << "setSortingEnabled(" << language::boolValue(false) << ')' << language::eol;
2252 }
2253 return tempName;
2254}
2255
2256void WriteInitialization::enableSorting(DomWidget *w, const QString &varName, const QString &tempName)
2257{
2258 if (!w->elementItem().isEmpty()) {
2259 m_refreshOut << m_indent << varName << language::derefPointer
2260 << "setSortingEnabled(" << tempName << ')' << language::eol << '\n';
2261 }
2262}
2263
2264/*
2265 * Initializers are just strings containing the function call and need to be prepended
2266 * the line indentation and the object they are supposed to initialize.
2267 * String initializers come with a preprocessor conditional (ifdef), so the code
2268 * compiles with QT_NO_xxx. A null pointer means no conditional. String initializers
2269 * are written to the retranslateUi() function, others to setupUi().
2270 */
2271
2272
2273/*!
2274 Create non-string inititializer.
2275 \param value the value to initialize the attribute with. May be empty, in which case
2276 the initializer is omitted.
2277 See above for other parameters.
2278*/
2279void WriteInitialization::addInitializer(Item *item, const QString &name,
2280 int column, const QString &value,
2281 const QString &directive, bool translatable)
2282{
2283 if (!value.isEmpty()) {
2284 QString setter;
2285 QTextStream str(&setter);
2286 str << language::derefPointer << "set" << name.at(0).toUpper() << QStringView{name}.mid(1) << '(';
2287 if (column >= 0)
2288 str << column << ", ";
2289 str << value << ')';
2291 str << ';';
2292 item->addSetter(setter, directive, translatable);
2293 }
2294}
2295
2296/*!
2297 Create string inititializer.
2298 \param initializers in/out list of inializers
2299 \param properties map property name -> property to extract data from
2300 \param name the property to extract
2301 \param col the item column to generate the initializer for. This is relevant for
2302 tree widgets only. If it is -1, no column index will be generated.
2303 \param ifdef preprocessor symbol for disabling compilation of this initializer
2304*/
2305void WriteInitialization::addStringInitializer(Item *item,
2306 const DomPropertyMap &properties, const QString &name, int column, const QString &directive) const
2307{
2308 if (const DomProperty *p = properties.value(name)) {
2309 DomString *str = p->elementString();
2310 QString text = toString(str);
2311 if (!text.isEmpty()) {
2312 bool translatable = needsTranslation(str);
2313 QString value = autoTrCall(str);
2314 addInitializer(item, name, column, value, directive, translatable);
2315 }
2316 }
2317}
2318
2319void WriteInitialization::addBrushInitializer(Item *item,
2320 const DomPropertyMap &properties, const QString &name, int column)
2321{
2322 if (const DomProperty *p = properties.value(name)) {
2323 if (p->elementBrush())
2324 addInitializer(item, name, column, writeBrushInitialization(p->elementBrush()));
2325 else if (p->elementColor())
2326 addInitializer(item, name, column, domColor2QString(p->elementColor()));
2327 }
2328}
2329
2330/*!
2331 Create inititializer for a flag value in the Qt namespace.
2332 If the named property is not in the map, the initializer is omitted.
2333*/
2334void WriteInitialization::addQtFlagsInitializer(Item *item, const DomPropertyMap &properties,
2335 const QString &name, int column)
2336{
2337 if (const DomProperty *p = properties.value(name)) {
2338 QString v = p->elementSet();
2339 if (!v.isEmpty()) {
2340 if (v.contains(u':')) {
2342 } else { // Qt 6 Legacy: Unqualified values
2343 const QString orOperator = u'|' + language::qtQualifier;
2344 v.replace(u'|', orOperator);
2345 v.prepend(language::qtQualifier);
2346 }
2347 addInitializer(item, name, column, v);
2348 }
2349 }
2350}
2351
2352/*!
2353 Create inititializer for an enum value in the Qt namespace.
2354 If the named property is not in the map, the initializer is omitted.
2355*/
2356void WriteInitialization::addQtEnumInitializer(Item *item,
2357 const DomPropertyMap &properties, const QString &name, int column) const
2358{
2359 if (const DomProperty *p = properties.value(name)) {
2360 QString v = p->elementEnum();
2361 if (!v.isEmpty()) {
2362 v = v.contains(u':') ? language::enumValue(v)
2363 : language::qtQualifier + v; // Qt 6 Legacy: Unqualified values
2364 addInitializer(item, name, column, v);
2365 }
2366 }
2367}
2368
2369/*!
2370 Create inititializers for all common properties that may be bound to a column.
2371*/
2372void WriteInitialization::addCommonInitializers(Item *item,
2373 const DomPropertyMap &properties, int column)
2374{
2375 if (const DomProperty *icon = properties.value("icon"_L1))
2376 addInitializer(item, "icon"_L1, column, iconCall(icon));
2377 addBrushInitializer(item, properties, "foreground"_L1, column);
2378 addBrushInitializer(item, properties, "background"_L1, column);
2379 if (const DomProperty *font = properties.value("font"_L1))
2380 addInitializer(item, "font"_L1, column, writeFontProperties(font->elementFont()));
2381 addQtFlagsInitializer(item, properties, "textAlignment"_L1, column);
2382 addQtEnumInitializer(item, properties, "checkState"_L1, column);
2383 addStringInitializer(item, properties, "text"_L1, column);
2384 addStringInitializer(item, properties, "toolTip"_L1, column,
2385 toolTipConfigKey());
2386 addStringInitializer(item, properties, "whatsThis"_L1, column,
2387 whatsThisConfigKey());
2388 addStringInitializer(item, properties, "statusTip"_L1, column,
2389 statusTipConfigKey());
2390}
2391
2392void WriteInitialization::initializeListWidget(DomWidget *w)
2393{
2394 const QString varName = m_driver->findOrInsertWidget(w);
2395
2396 const auto &items = w->elementItem();
2397
2398 if (items.isEmpty())
2399 return;
2400
2401 QString tempName = disableSorting(w, varName);
2402 // items
2403 // TODO: the generated code should be data-driven to reduce its size
2404 for (int i = 0; i < items.size(); ++i) {
2405 const DomItem *domItem = items.at(i);
2406
2407 const DomPropertyMap properties = propertyMap(domItem->elementProperty());
2408
2409 Item item("QListWidgetItem"_L1, m_indent, m_output, m_refreshOut, m_driver);
2410 addQtFlagsInitializer(&item, properties, "flags"_L1);
2411 addCommonInitializers(&item, properties);
2412
2413 item.writeSetupUi(varName);
2414 QString parentPath;
2415 QTextStream(&parentPath) << varName << language::derefPointer << "item(" << i << ')';
2416 item.writeRetranslateUi(parentPath);
2417 }
2418 enableSorting(w, varName, tempName);
2419}
2420
2421void WriteInitialization::initializeTreeWidget(DomWidget *w)
2422{
2423 const QString varName = m_driver->findOrInsertWidget(w);
2424
2425 // columns
2426 Item item("QTreeWidgetItem"_L1, m_indent, m_output, m_refreshOut, m_driver);
2427
2428 const auto &columns = w->elementColumn();
2429 for (int i = 0; i < columns.size(); ++i) {
2430 const DomColumn *column = columns.at(i);
2431
2432 const DomPropertyMap properties = propertyMap(column->elementProperty());
2433 addCommonInitializers(&item, properties, i);
2434
2435 if (const DomProperty *p = properties.value("text"_L1)) {
2436 DomString *str = p->elementString();
2437 if (str && str->text().isEmpty()) {
2438 m_output << m_indent << varName << language::derefPointer
2439 << "headerItem()" << language::derefPointer << "setText("
2440 << i << ", " << language::emptyString << ')' << language::eol;
2441 }
2442 }
2443 }
2444 const QString itemName = item.writeSetupUi(QString(), Item::DontConstruct);
2445 item.writeRetranslateUi(varName + language::derefPointer + "headerItem()"_L1);
2446 if (!itemName.isNull()) {
2447 m_output << m_indent << varName << language::derefPointer
2448 << "setHeaderItem(" << itemName << ')' << language::eol;
2449 }
2450
2451 if (w->elementItem().empty())
2452 return;
2453
2454 QString tempName = disableSorting(w, varName);
2455
2456 const auto items = initializeTreeWidgetItems(w->elementItem());
2457 for (int i = 0; i < items.size(); i++) {
2458 Item *itm = items[i];
2459 itm->writeSetupUi(varName);
2460 QString parentPath;
2461 QTextStream(&parentPath) << varName << language::derefPointer << "topLevelItem(" << i << ')';
2462 itm->writeRetranslateUi(parentPath);
2463 delete itm;
2464 }
2465
2466 enableSorting(w, varName, tempName);
2467}
2468
2469/*!
2470 Create and write out initializers for tree widget items.
2471 This function makes sure that only needed items are fetched (subject to preprocessor
2472 conditionals), that each item is fetched from its parent widget/item exactly once
2473 and that no temporary variables are created for items that are needed only once. As
2474 fetches are built top-down from the root, but determining how often and under which
2475 conditions an item is needed needs to be done bottom-up, the whole process makes
2476 two passes, storing the intermediate result in a recursive StringInitializerListMap.
2477*/
2478WriteInitialization::Items WriteInitialization::initializeTreeWidgetItems(const QList<DomItem *> &domItems)
2479{
2480 // items
2481 Items items;
2482 const qsizetype numDomItems = domItems.size();
2483 items.reserve(numDomItems);
2484
2485 for (qsizetype i = 0; i < numDomItems; ++i) {
2486 const DomItem *domItem = domItems.at(i);
2487
2488 Item *item = new Item("QTreeWidgetItem"_L1, m_indent, m_output, m_refreshOut, m_driver);
2489 items << item;
2490
2491 QHash<QString, DomProperty *> map;
2492
2493 int col = -1;
2494 const DomPropertyList properties = domItem->elementProperty();
2495 for (DomProperty *p : properties) {
2496 if (p->attributeName() == "text"_L1) {
2497 if (!map.isEmpty()) {
2498 addCommonInitializers(item, map, col);
2499 map.clear();
2500 }
2501 col++;
2502 }
2503 map.insert(p->attributeName(), p);
2504 }
2505 addCommonInitializers(item, map, col);
2506 // AbstractFromBuilder saves flags last, so they always end up in the last column's map.
2507 addQtFlagsInitializer(item, map, "flags"_L1);
2508
2509 const auto subItems = initializeTreeWidgetItems(domItem->elementItem());
2510 for (Item *subItem : subItems)
2511 item->addChild(subItem);
2512 }
2513 return items;
2514}
2515
2516void WriteInitialization::initializeTableWidget(DomWidget *w)
2517{
2518 const QString varName = m_driver->findOrInsertWidget(w);
2519
2520 // columns
2521 const auto &columns = w->elementColumn();
2522
2523 if (!columns.empty()) {
2524 m_output << m_indent << "if (" << varName << language::derefPointer
2525 << "columnCount() < " << columns.size() << ')';
2526 if (language::language() == Language::Python)
2527 m_output << ':';
2528 m_output << '\n' << m_dindent << varName << language::derefPointer << "setColumnCount("
2529 << columns.size() << ')' << language::eol;
2530 }
2531
2532 for (int i = 0; i < columns.size(); ++i) {
2533 const DomColumn *column = columns.at(i);
2534 if (!column->elementProperty().isEmpty()) {
2535 const DomPropertyMap properties = propertyMap(column->elementProperty());
2536
2537 Item item("QTableWidgetItem"_L1, m_indent, m_output, m_refreshOut, m_driver);
2538 addCommonInitializers(&item, properties);
2539
2540 QString itemName = item.writeSetupUi(QString(), Item::ConstructItemAndVariable);
2541 QString parentPath;
2542 QTextStream(&parentPath) << varName << language::derefPointer
2543 << "horizontalHeaderItem(" << i << ')';
2544 item.writeRetranslateUi(parentPath);
2545 m_output << m_indent << varName << language::derefPointer << "setHorizontalHeaderItem("
2546 << i << ", " << itemName << ')' << language::eol;
2547 }
2548 }
2549
2550 // rows
2551 const auto &rows = w->elementRow();
2552
2553 if (!rows.isEmpty()) {
2554 m_output << m_indent << "if (" << varName << language::derefPointer
2555 << "rowCount() < " << rows.size() << ')';
2556 if (language::language() == Language::Python)
2557 m_output << ':';
2558 m_output << '\n' << m_dindent << varName << language::derefPointer << "setRowCount("
2559 << rows.size() << ')' << language::eol;
2560 }
2561
2562 for (int i = 0; i < rows.size(); ++i) {
2563 const DomRow *row = rows.at(i);
2564 if (!row->elementProperty().isEmpty()) {
2565 const DomPropertyMap properties = propertyMap(row->elementProperty());
2566
2567 Item item("QTableWidgetItem"_L1, m_indent, m_output, m_refreshOut, m_driver);
2568 addCommonInitializers(&item, properties);
2569
2570 QString itemName = item.writeSetupUi(QString(), Item::ConstructItemAndVariable);
2571 QString parentPath;
2572 QTextStream(&parentPath) << varName << language::derefPointer << "verticalHeaderItem(" << i << ')';
2573 item.writeRetranslateUi(parentPath);
2574 m_output << m_indent << varName << language::derefPointer << "setVerticalHeaderItem("
2575 << i << ", " << itemName << ')' << language::eol;
2576 }
2577 }
2578
2579 // items
2580 QString tempName = disableSorting(w, varName);
2581
2582 const auto &items = w->elementItem();
2583
2584 for (const DomItem *cell : items) {
2585 if (cell->hasAttributeRow() && cell->hasAttributeColumn() && !cell->elementProperty().isEmpty()) {
2586 const int r = cell->attributeRow();
2587 const int c = cell->attributeColumn();
2588 const DomPropertyMap properties = propertyMap(cell->elementProperty());
2589
2590 Item item("QTableWidgetItem"_L1, m_indent, m_output, m_refreshOut, m_driver);
2591 addQtFlagsInitializer(&item, properties, "flags"_L1);
2592 addCommonInitializers(&item, properties);
2593
2594 QString itemName = item.writeSetupUi(QString(), Item::ConstructItemAndVariable);
2595 QString parentPath;
2596 QTextStream(&parentPath) << varName << language::derefPointer << "item(" << r
2597 << ", " << c << ')';
2598 item.writeRetranslateUi(parentPath);
2599 m_output << m_indent << varName << language::derefPointer << "setItem("
2600 << r << ", " << c << ", " << itemName << ')' << language::eol;
2601 }
2602 }
2603 enableSorting(w, varName, tempName);
2604}
2605
2606QString WriteInitialization::trCall(const QString &str, const QString &commentHint, const QString &id) const
2607{
2608 if (str.isEmpty())
2609 return language::emptyString;
2610
2611 QString result;
2612 QTextStream ts(&result);
2613
2614 const bool idBasedTranslations = m_driver->useIdBasedTranslations();
2615 if (m_option.translateFunction.isEmpty()) {
2616 if (idBasedTranslations || m_option.idBased) {
2617 ts << "qtTrId(";
2618 } else {
2619 ts << "QCoreApplication" << language::qualifier << "translate("
2620 << '"' << m_generatedClass << "\", ";
2621 }
2622 } else {
2623 ts << m_option.translateFunction << '(';
2624 }
2625
2626 ts << language::charliteral(idBasedTranslations ? id : str, m_dindent);
2627
2628 if (!idBasedTranslations && !m_option.idBased) {
2629 ts << ", ";
2630 if (commentHint.isEmpty())
2631 ts << language::nullPtr;
2632 else
2633 ts << language::charliteral(commentHint, m_dindent);
2634 }
2635
2636 ts << ')';
2637 return result;
2638}
2639
2640void WriteInitialization::initializeMenu(DomWidget *w, const QString &/*parentWidget*/)
2641{
2642 const QString menuName = m_driver->findOrInsertWidget(w);
2643 const QString menuAction = menuName + "Action"_L1;
2644
2645 const DomAction *action = m_driver->actionByName(menuAction);
2646 if (action && action->hasAttributeMenu()) {
2647 m_output << m_indent << menuAction << " = " << menuName
2648 << language::derefPointer << "menuAction()" << language::eol;
2649 }
2650}
2651
2652QString WriteInitialization::trCall(DomString *str, const QString &defaultString) const
2653{
2654 QString value = defaultString;
2655 QString comment;
2656 QString id;
2657 if (str) {
2658 value = toString(str);
2659 comment = str->attributeComment();
2660 id = str->attributeId();
2661 }
2662 return trCall(value, comment, id);
2663}
2664
2665QString WriteInitialization::noTrCall(DomString *str, const QString &defaultString) const
2666{
2667 QString value = defaultString;
2668 if (!str && defaultString.isEmpty())
2669 return {};
2670 if (str)
2671 value = str->text();
2672 QString ret;
2673 QTextStream ts(&ret);
2674 ts << language::qstring(value, m_dindent);
2675 return ret;
2676}
2677
2678QString WriteInitialization::autoTrCall(DomString *str, const QString &defaultString) const
2679{
2680 if ((!str && !defaultString.isEmpty()) || needsTranslation(str))
2681 return trCall(str, defaultString);
2682 return noTrCall(str, defaultString);
2683}
2684
2685QTextStream &WriteInitialization::autoTrOutput(const DomProperty *property)
2686{
2687 if (const DomString *str = property->elementString())
2688 return autoTrOutput(str);
2689 if (const DomStringList *list = property->elementStringList())
2690 if (needsTranslation(list))
2691 return m_refreshOut;
2692 return m_output;
2693}
2694
2695QTextStream &WriteInitialization::autoTrOutput(const DomString *str, const QString &defaultString)
2696{
2697 if ((!str && !defaultString.isEmpty()) || needsTranslation(str))
2698 return m_refreshOut;
2699 return m_output;
2700}
2701
2702WriteInitialization::Declaration WriteInitialization::findDeclaration(const QString &name)
2703{
2704 if (const DomWidget *widget = m_driver->widgetByName(name))
2705 return {m_driver->findOrInsertWidget(widget), widget->attributeClass()};
2706 if (const DomAction *action = m_driver->actionByName(name))
2707 return {m_driver->findOrInsertAction(action), QStringLiteral("QAction")};
2708 if (const DomButtonGroup *group = m_driver->findButtonGroup(name))
2709 return {m_driver->findOrInsertButtonGroup(group), QStringLiteral("QButtonGroup")};
2710 return {};
2711}
2712
2713bool WriteInitialization::isCustomWidget(const QString &className) const
2714{
2715 return m_uic->customWidgetsInfo()->customWidget(className) != nullptr;
2716}
2717
2718ConnectionSyntax WriteInitialization::connectionSyntax(const language::SignalSlot &sender,
2719 const language::SignalSlot &receiver) const
2720{
2723 if (m_option.forceStringConnectionSyntax)
2725 // Auto mode: Use Qt 5 connection syntax for Qt classes and parameterless
2726 // connections. QAxWidget is special though since it has a fake Meta object.
2727 static const QStringList requiresStringSyntax{QStringLiteral("QAxWidget")};
2728 if (requiresStringSyntax.contains(sender.className)
2729 || requiresStringSyntax.contains(receiver.className)) {
2731 }
2732
2733 if ((sender.name == m_mainFormVarName && m_customSignals.contains(sender.signature))
2734 || (receiver.name == m_mainFormVarName && m_customSlots.contains(receiver.signature))) {
2736 }
2737
2738 return sender.signature.endsWith("()"_L1)
2739 || (!isCustomWidget(sender.className) && !isCustomWidget(receiver.className))
2741}
2742
2743void WriteInitialization::acceptConnection(DomConnection *connection)
2744{
2745 const QString senderName = connection->elementSender();
2746 const QString receiverName = connection->elementReceiver();
2747
2748 const auto senderDecl = findDeclaration(senderName);
2749 const auto receiverDecl = findDeclaration(receiverName);
2750
2751 if (senderDecl.name.isEmpty() || receiverDecl.name.isEmpty()) {
2752 QString message;
2753 QTextStream(&message) << m_option.messagePrefix()
2754 << ": Warning: Invalid signal/slot connection: \""
2755 << senderName << "\" -> \"" << receiverName << "\".";
2756 fprintf(stderr, "%s\n", qPrintable(message));
2757 return;
2758 }
2759 const QString senderSignature = connection->elementSignal();
2760 const QString slotSignature = connection->elementSlot();
2761 const bool senderAmbiguous = m_uic->customWidgetsInfo()->isAmbiguousSignal(senderDecl.className,
2762 senderSignature);
2763 const bool slotAmbiguous = m_uic->customWidgetsInfo()->isAmbiguousSlot(receiverDecl.className,
2764 slotSignature);
2765
2766 language::SignalSlotOptions signalOptions;
2767 signalOptions.setFlag(language::SignalSlotOption::Ambiguous, senderAmbiguous);
2768 language::SignalSlotOptions slotOptions;
2769 slotOptions.setFlag(language::SignalSlotOption::Ambiguous, slotAmbiguous);
2770
2771 language::SignalSlot theSignal{senderDecl.name, senderSignature,
2772 senderDecl.className, signalOptions};
2773 language::SignalSlot theSlot{receiverDecl.name, slotSignature,
2774 receiverDecl.className, slotOptions};
2775
2776 m_output << m_indent;
2777 language::formatConnection(m_output, theSignal, theSlot,
2778 connectionSyntax(theSignal, theSlot));
2779 m_output << language::eol;
2780}
2781
2782static void generateMultiDirectiveBegin(QTextStream &outputStream, const QSet<QString> &directives)
2783{
2784 if (directives.isEmpty())
2785 return;
2786
2787 if (directives.size() == 1) {
2788 outputStream << language::openQtConfig(*directives.cbegin());
2789 return;
2790 }
2791
2792 auto list = directives.values();
2793 // sort (always generate in the same order):
2794 std::sort(list.begin(), list.end());
2795
2796 outputStream << "#if " << language::qtConfig(list.constFirst());
2797 for (qsizetype i = 1, size = list.size(); i < size; ++i)
2798 outputStream << " || " << language::qtConfig(list.at(i));
2799 outputStream << Qt::endl;
2800}
2801
2802static void generateMultiDirectiveEnd(QTextStream &outputStream, const QSet<QString> &directives)
2803{
2804 if (directives.isEmpty())
2805 return;
2806
2807 outputStream << "#endif" << Qt::endl;
2808}
2809
2810WriteInitialization::Item::Item(const QString &itemClassName, const QString &indent, QTextStream &setupUiStream, QTextStream &retranslateUiStream, Driver *driver)
2811 :
2812 m_itemClassName(itemClassName),
2813 m_indent(indent),
2814 m_setupUiStream(setupUiStream),
2815 m_retranslateUiStream(retranslateUiStream),
2816 m_driver(driver)
2817{
2818
2819}
2820
2821WriteInitialization::Item::~Item()
2822{
2823 qDeleteAll(m_children);
2824}
2825
2826QString WriteInitialization::Item::writeSetupUi(const QString &parent, Item::EmptyItemPolicy emptyItemPolicy)
2827{
2828 if (emptyItemPolicy == Item::DontConstruct && m_setupUiData.policy == ItemData::DontGenerate)
2829 return {};
2830
2831 bool generateMultiDirective = false;
2832 if (emptyItemPolicy == Item::ConstructItemOnly && m_children.isEmpty()) {
2833 if (m_setupUiData.policy == ItemData::DontGenerate) {
2834 m_setupUiStream << m_indent << language::operatorNew << m_itemClassName
2835 << '(' << parent << ')' << language::eol;
2836 return {};
2837 }
2838 if (m_setupUiData.policy == ItemData::GenerateWithMultiDirective)
2839 generateMultiDirective = true;
2840 }
2841
2842 if (generateMultiDirective)
2843 generateMultiDirectiveBegin(m_setupUiStream, m_setupUiData.directives);
2844
2845 const QString uniqueName = m_driver->unique("__"_L1 + m_itemClassName.toLower());
2846 m_setupUiStream << m_indent;
2847 if (language::language() == Language::Cpp)
2848 m_setupUiStream << m_itemClassName << " *";
2849 m_setupUiStream << uniqueName
2850 << " = " << language::operatorNew << m_itemClassName << '(' << parent
2851 << ')' << language::eol;
2852
2853 if (generateMultiDirective) {
2854 m_setupUiStream << "#else\n";
2855 m_setupUiStream << m_indent << language::operatorNew << m_itemClassName
2856 << '(' << parent << ')' << language::eol;
2857 generateMultiDirectiveEnd(m_setupUiStream, m_setupUiData.directives);
2858 }
2859
2860 QMultiMap<QString, QString>::ConstIterator it = m_setupUiData.setters.constBegin();
2861 while (it != m_setupUiData.setters.constEnd()) {
2862 if (!it.key().isEmpty())
2863 m_setupUiStream << language::openQtConfig(it.key());
2864 m_setupUiStream << m_indent << uniqueName << it.value() << Qt::endl;
2865 if (!it.key().isEmpty())
2866 m_setupUiStream << language::closeQtConfig(it.key());
2867 ++it;
2868 }
2869 for (Item *child : std::as_const(m_children))
2870 child->writeSetupUi(uniqueName);
2871 return uniqueName;
2872}
2873
2874void WriteInitialization::Item::writeRetranslateUi(const QString &parentPath)
2875{
2876 if (m_retranslateUiData.policy == ItemData::DontGenerate)
2877 return;
2878
2879 if (m_retranslateUiData.policy == ItemData::GenerateWithMultiDirective)
2880 generateMultiDirectiveBegin(m_retranslateUiStream, m_retranslateUiData.directives);
2881
2882 const QString uniqueName = m_driver->unique("___"_L1 + m_itemClassName.toLower());
2883 m_retranslateUiStream << m_indent;
2884 if (language::language() == Language::Cpp)
2885 m_retranslateUiStream << m_itemClassName << " *";
2886 m_retranslateUiStream << uniqueName << " = " << parentPath << language::eol;
2887
2888 if (m_retranslateUiData.policy == ItemData::GenerateWithMultiDirective)
2889 generateMultiDirectiveEnd(m_retranslateUiStream, m_retranslateUiData.directives);
2890
2891 QString oldDirective;
2892 QMultiMap<QString, QString>::ConstIterator it = m_retranslateUiData.setters.constBegin();
2893 while (it != m_retranslateUiData.setters.constEnd()) {
2894 const QString newDirective = it.key();
2895 if (oldDirective != newDirective) {
2896 if (!oldDirective.isEmpty())
2897 m_retranslateUiStream << language::closeQtConfig(oldDirective);
2898 if (!newDirective.isEmpty())
2899 m_retranslateUiStream << language::openQtConfig(newDirective);
2900 oldDirective = newDirective;
2901 }
2902 m_retranslateUiStream << m_indent << uniqueName << it.value() << Qt::endl;
2903 ++it;
2904 }
2905 if (!oldDirective.isEmpty())
2906 m_retranslateUiStream << language::closeQtConfig(oldDirective);
2907
2908 for (int i = 0; i < m_children.size(); i++) {
2909 QString method;
2910 QTextStream(&method) << uniqueName << language::derefPointer << "child(" << i << ')';
2911 m_children[i]->writeRetranslateUi(method);
2912 }
2913}
2914
2915void WriteInitialization::Item::addSetter(const QString &setter, const QString &directive, bool translatable)
2916{
2918 if (translatable) {
2919 m_retranslateUiData.setters.insert(directive, setter);
2920 if (ItemData::GenerateWithMultiDirective == newPolicy)
2921 m_retranslateUiData.directives << directive;
2922 if (m_retranslateUiData.policy < newPolicy)
2923 m_retranslateUiData.policy = newPolicy;
2924 } else {
2925 m_setupUiData.setters.insert(directive, setter);
2926 if (ItemData::GenerateWithMultiDirective == newPolicy)
2927 m_setupUiData.directives << directive;
2928 if (m_setupUiData.policy < newPolicy)
2929 m_setupUiData.policy = newPolicy;
2930 }
2931}
2932
2933void WriteInitialization::Item::addChild(Item *child)
2934{
2935 m_children << child;
2936 child->m_parent = this;
2937
2938 Item *c = child;
2939 Item *p = this;
2940 while (p) {
2941 p->m_setupUiData.directives |= c->m_setupUiData.directives;
2942 p->m_retranslateUiData.directives |= c->m_retranslateUiData.directives;
2943 if (p->m_setupUiData.policy < c->m_setupUiData.policy)
2944 p->m_setupUiData.policy = c->m_setupUiData.policy;
2945 if (p->m_retranslateUiData.policy < c->m_retranslateUiData.policy)
2946 p->m_retranslateUiData.policy = c->m_retranslateUiData.policy;
2947 c = p;
2948 p = p->m_parent;
2949 }
2950}
2951
2952
2953} // namespace CPP
2954
2955QT_END_NAMESPACE
FontHandle(const DomFont *domFont)
int compare(const FontHandle &) const
int compare(const IconHandle &) const
IconHandle(const DomResourceIcon *domIcon)
SizePolicyHandle(const DomSizePolicy *domSizePolicy)
int compare(const SizePolicyHandle &) const
bool isAmbiguousSlot(const QString &className, const QString &slotSignature) const
bool isAmbiguousSignal(const QString &className, const QString &signalSignature) const
QString simpleContainerAddPageMethod(const QString &name) const
DomCustomWidget * customWidget(const QString &name) const
const DomAction * actionByName(const QString &attributeName) const
Definition driver.cpp:306
QString unique(const QString &instanceName=QString(), const QString &className=QString())
Definition driver.cpp:137
bool useIdBasedTranslations() const
Definition driver.h:68
QString findOrInsertWidget(const DomWidget *ui_widget)
Definition driver.cpp:66
const DomWidget * widgetByName(const QString &attributeName) const
Definition driver.cpp:290
QString findOrInsertActionGroup(const DomActionGroup *ui_group)
Definition driver.cpp:101
const DomButtonGroup * findButtonGroup(const QString &attributeName) const
Definition driver.cpp:117
\inmodule QtCore
Definition qhash.h:844
Definition qlist.h:82
\inmodule QtCore
QVersionNumber() noexcept
Produces a null version.
Definition uic.h:31
bool isButton(const QString &className) const
Definition uic.cpp:301
const DatabaseInfo * databaseInfo() const
Definition uic.h:54
const CustomWidgetsInfo * customWidgetsInfo() const
Definition uic.h:57
bool isMenu(const QString &className) const
Definition uic.cpp:323
bool isContainer(const QString &className) const
Definition uic.cpp:311
const Option & option() const
Definition uic.h:45
Driver * driver() const
Definition uic.h:39
static QString whatsThisConfigKey()
static QString toolTipConfigKey()
static QString accessibilityConfigKey()
static QString statusTipConfigKey()
static QString shortcutConfigKey()
ConnectionSyntax
Definition language.h:15
Language
Definition language.h:13
static void generateMultiDirectiveEnd(QTextStream &outputStream, const QSet< QString > &directives)
static QVersionNumber colorRoleVersionAdded(const QString &roleName)
static bool needsTranslation(const DomElement *element)
static void writeResourceIcon(QTextStream &output, const QString &iconName, const QString &indent, const DomResourceIcon *i)
static void generateMultiDirectiveBegin(QTextStream &outputStream, const QSet< QString > &directives)
static QString configKeyForProperty(const QString &propertyName)
static QString fontWeight(const DomFont *domFont)
static QString layoutAddMethod(DomLayoutItem::Kind kind, const QString &layoutClass)
static QString formLayoutRole(int column, int colspan)
static void writeIconAddPixmap(QTextStream &output, const QString &indent, const QString &iconName, const QString &call, const char *mode, const char *state)
static void writeContentsMargins(const QString &indent, const QString &objectName, int value, QTextStream &str)
static void writeIconAddFile(QTextStream &output, const QString &indent, const QString &iconName, const QString &fileName, const char *mode, const char *state)
Combined button and popup list for selecting options.
const QString & asString(const QString &s)
Definition qstring.h:1700
QString self
Definition language.cpp:61
Language language()
Definition language.cpp:19
QString qtQualifier
Definition language.cpp:59
QString enumValue(const QString &value)
Definition language.cpp:522
QString emptyString
Definition language.cpp:63
QString nullPtr
Definition language.cpp:57
_string< true > qstring
Definition language.h:111
QString eol
Definition language.cpp:62
QString qualifier
Definition language.cpp:60
SignalSlotOption
Definition language.h:177
void formatConnection(QTextStream &str, const SignalSlot &sender, const SignalSlot &receiver, ConnectionSyntax connectionSyntax)
Definition language.cpp:475
QString operatorNew
Definition language.cpp:58
QString derefPointer
Definition language.cpp:54
#define qPrintable(string)
Definition qstring.h:1705
#define QStringLiteral(str)
Definition qstring.h:1847
void acceptCustomWidgets(DomCustomWidgets *node) override
void acceptActionGroup(DomActionGroup *node) override
void acceptSpacer(DomSpacer *node) override
void acceptLayoutItem(DomLayoutItem *node) override
void acceptTabStops(DomTabStops *tabStops) override
void acceptUI(DomUI *node) override
QList< DomProperty * > DomPropertyList
void acceptLayoutDefault(DomLayoutDefault *node) override
void acceptLayout(DomLayout *node) override
void acceptAction(DomAction *node) override
void acceptCustomWidget(DomCustomWidget *node) override
void acceptLayoutFunction(DomLayoutFunction *node) override
void acceptActionRef(DomActionRef *node) override
void acceptConnection(DomConnection *connection) override
QHash< QString, DomProperty * > DomPropertyMap
void acceptWidget(DomWidget *node) override
iconFromTheme(const QString &theme)
unsigned int idBased
Definition option.h:29
unsigned int forceMemberFnPtrConnectionSyntax
Definition option.h:30
unsigned int forceStringConnectionSyntax
Definition option.h:31
unsigned int autoConnection
Definition option.h:25
virtual void acceptActionGroup(DomActionGroup *actionGroup)
virtual void acceptLayoutItem(DomLayoutItem *layoutItem)
virtual void acceptCustomWidgets(DomCustomWidgets *customWidgets)
virtual void acceptWidget(DomWidget *widget)
virtual void acceptConnections(DomConnections *connections)
virtual void acceptLayout(DomLayout *layout)