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