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