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