1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the tools applications of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
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.
fixQtEnumerationName(QString & name)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.
toolBarAreaStringFromDOMAttributes(const CPP::WriteInitialization::DomPropertyMap & attributes)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.
writeSpacerItem(const DomSpacer * node,QTextStream & output)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.
compareInt(int i1,int i2)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>
writeSetter(const QString & indent,const QString & varName,const QString & setter,Value v,QTextStream & str)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 
writeSetupUIScriptVariableDeclarations(const QString & indent,QTextStream & str)137     void writeSetupUIScriptVariableDeclarations(const QString &indent, QTextStream &str)  {
138         str << indent << "ScriptContext scriptContext;\n"
139             << indent << "QWidgetList childWidgets;\n";
140     }
141 
iconHasStatePixmaps(const DomResourceIcon * i)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 
isIconFormat44(const DomResourceIcon * i)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'
checkProperty(const QString & fileName,const DomProperty * p)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 
openIfndef(QTextStream & str,const QString & symbol)183     inline void openIfndef(QTextStream &str, const QString &symbol) { if (!symbol.isEmpty()) str << QLatin1String("#ifndef ") << symbol << endl;  }
closeIfndef(QTextStream & str,const QString & symbol)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 
FontHandle(const DomFont * domFont)195 FontHandle::FontHandle(const DomFont *domFont) :
196       m_domFont(domFont)
197 {
198 }
199 
compare(const FontHandle & rhs) const200 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 
IconHandle(const DomResourceIcon * domIcon)258 IconHandle::IconHandle(const DomResourceIcon *domIcon) :
259       m_domIcon(domIcon)
260 {
261 }
262 
compare(const IconHandle & rhs) const263 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)
qHash(const SizePolicyHandle & handle)316 inline uint qHash(const SizePolicyHandle &handle) { return qHash(handle.m_domSizePolicy); }
qHash(const FontHandle & handle)317 inline uint qHash(const FontHandle &handle) { return qHash(handle.m_domFont); }
qHash(const IconHandle & handle)318 inline uint qHash(const IconHandle &handle) { return qHash(handle.m_domIcon); }
319 #endif
320 
SizePolicyHandle(const DomSizePolicy * domSizePolicy)321 SizePolicyHandle::SizePolicyHandle(const DomSizePolicy *domSizePolicy) :
322     m_domSizePolicy(domSizePolicy)
323 {
324 }
325 
compare(const SizePolicyHandle & rhs) const326 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 
LayoutDefaultHandler()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 
acceptLayoutDefault(DomLayoutDefault * node)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 
acceptLayoutFunction(DomLayoutFunction * node)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 
writeContentsMargins(const QString & indent,const QString & objectName,int value,QTextStream & str)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 
writeProperty(int p,const QString & indent,const QString & objectName,const DomPropertyMap & properties,const QString & propertyName,const QString & setter,int defaultStyleValue,bool suppressDefault,QTextStream & str) const408 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 
writeProperties(const QString & indent,const QString & varName,const DomPropertyMap & properties,int marginType,bool suppressMarginDefault,QTextStream & str) const454 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 
needsTranslation(DomString * str)469 static bool needsTranslation(DomString *str)
470 {
471     if (!str)
472         return false;
473     return !str->hasAttributeNotr() || !toBool(str->attributeNotr());
474 }
475 
476 // ---  WriteInitialization
WriteInitialization(Uic * uic,bool activateScripts)477 WriteInitialization::WriteInitialization(Uic *uic, bool activateScripts) :
478       m_uic(uic),
479       m_driver(uic->driver()), m_output(uic->output()), m_option(uic->option()),
480       m_indent(m_option.indent + m_option.indent),
481       m_dindent(m_indent + m_option.indent),
482       m_stdsetdef(true),
483       m_layoutMarginType(TopLevelMargin),
484       m_mainFormUsedInRetranslateUi(false),
485       m_delayedOut(&m_delayedInitialization, QIODevice::WriteOnly),
486       m_refreshOut(&m_refreshInitialization, QIODevice::WriteOnly),
487       m_actionOut(&m_delayedActionInitialization, QIODevice::WriteOnly),
488       m_activateScripts(activateScripts), m_layoutWidget(false),
489       m_firstThemeIcon(true)
490 {
491 }
492 
acceptUI(DomUI * node)493 void WriteInitialization::acceptUI(DomUI *node)
494 {
495     m_registeredImages.clear();
496     m_actionGroupChain.push(0);
497     m_widgetChain.push(0);
498     m_layoutChain.push(0);
499 
500     acceptLayoutDefault(node->elementLayoutDefault());
501     acceptLayoutFunction(node->elementLayoutFunction());
502 
503     if (node->elementCustomWidgets())
504         TreeWalker::acceptCustomWidgets(node->elementCustomWidgets());
505 
506     if (node->elementImages())
507         TreeWalker::acceptImages(node->elementImages());
508 
509     if (m_option.generateImplemetation)
510         m_output << "#include <" << m_driver->headerFileName() << ">\n\n";
511 
512     m_stdsetdef = true;
513     if (node->hasAttributeStdSetDef())
514         m_stdsetdef = node->attributeStdSetDef();
515 
516     const QString className = node->elementClass() + m_option.postfix;
517     m_generatedClass = className;
518 
519     const QString varName = m_driver->findOrInsertWidget(node->elementWidget());
520     m_mainFormVarName = varName;
521     m_registeredWidgets.insert(varName, node->elementWidget()); // register the main widget
522 
523     const QString widgetClassName = node->elementWidget()->attributeClass();
524 
525     m_output << m_option.indent << "void " << "setupUi(" << widgetClassName << " *" << varName << ")\n"
526            << m_option.indent << "{\n";
527 
528     if (m_activateScripts)
529         writeSetupUIScriptVariableDeclarations(m_indent, m_output);
530 
531     const QStringList connections = m_uic->databaseInfo()->connections();
532     for (int i=0; i<connections.size(); ++i) {
533         QString connection = connections.at(i);
534 
535         if (connection == QLatin1String("(default)"))
536             continue;
537 
538         const QString varConn = connection + QLatin1String("Connection");
539         m_output << m_indent << varConn << " = QSqlDatabase::database(" << fixString(connection, m_dindent) << ");\n";
540     }
541 
542     acceptWidget(node->elementWidget());
543 
544     if (m_buddies.size() > 0)
545         openIfndef(m_output, QLatin1String(shortcutDefineC));
546     for (int i=0; i<m_buddies.size(); ++i) {
547         const Buddy &b = m_buddies.at(i);
548 
549         if (!m_registeredWidgets.contains(b.objName)) {
550             fprintf(stderr, "%s: Warning: Buddy assignment: '%s' is not a valid widget.\n",
551                     qPrintable(m_option.messagePrefix()),
552                     b.objName.toLatin1().data());
553             continue;
554         } else if (!m_registeredWidgets.contains(b.buddy)) {
555             fprintf(stderr, "%s: Warning: Buddy assignment: '%s' is not a valid widget.\n",
556                     qPrintable(m_option.messagePrefix()),
557                     b.buddy.toLatin1().data());
558             continue;
559         }
560 
561         m_output << m_indent << b.objName << "->setBuddy(" << b.buddy << ");\n";
562     }
563     if (m_buddies.size() > 0)
564         closeIfndef(m_output, QLatin1String(shortcutDefineC));
565 
566     if (node->elementTabStops())
567         acceptTabStops(node->elementTabStops());
568 
569     if (m_delayedActionInitialization.size())
570         m_output << "\n" << m_delayedActionInitialization;
571 
572     m_output << "\n" << m_indent << "retranslateUi(" << varName << ");\n";
573 
574     if (node->elementConnections())
575         acceptConnections(node->elementConnections());
576 
577     if (!m_delayedInitialization.isEmpty())
578         m_output << "\n" << m_delayedInitialization << "\n";
579 
580     if (m_option.autoConnection)
581         m_output << "\n" << m_indent << "QMetaObject::connectSlotsByName(" << varName << ");\n";
582 
583     m_output << m_option.indent << "} // setupUi\n\n";
584 
585     if (!m_mainFormUsedInRetranslateUi) {
586         m_refreshInitialization += m_indent;
587         m_refreshInitialization += QLatin1String("Q_UNUSED(");
588         m_refreshInitialization += varName ;
589         m_refreshInitialization += QLatin1String(");\n");
590     }
591 
592     m_output << m_option.indent << "void " << "retranslateUi(" << widgetClassName << " *" << varName << ")\n"
593            << m_option.indent << "{\n"
594            << m_refreshInitialization
595            << m_option.indent << "} // retranslateUi\n\n";
596 
597     m_layoutChain.pop();
598     m_widgetChain.pop();
599     m_actionGroupChain.pop();
600 }
601 
addWizardPage(const QString & pageVarName,const DomWidget * page,const QString & parentWidget)602 void WriteInitialization::addWizardPage(const QString &pageVarName, const DomWidget *page, const QString &parentWidget)
603 {
604     /* If the node has a (free-format) string "pageId" attribute (which could
605      * an integer or an enumeration value), use setPage(), else addPage(). */
606     QString id;
607     const DomPropertyList attributes = page->elementAttribute();
608     if (!attributes.empty()) {
609         const DomPropertyList::const_iterator acend = attributes.constEnd();
610         for (DomPropertyList::const_iterator it = attributes.constBegin(); it != acend; ++it)
611             if ((*it)->attributeName() == QLatin1String("pageId")) {
612                 if (const DomString *ds = (*it)->elementString())
613                     id = ds->text();
614                 break;
615             }
616     }
617     if (id.isEmpty()) {
618         m_output << m_indent << parentWidget << "->addPage(" << pageVarName << ");\n";
619     } else {
620         m_output << m_indent << parentWidget << "->setPage(" << id << ", " << pageVarName << ");\n";
621     }
622 }
623 
acceptWidget(DomWidget * node)624 void WriteInitialization::acceptWidget(DomWidget *node)
625 {
626     m_layoutMarginType = m_widgetChain.count() == 1 ? TopLevelMargin : ChildMargin;
627     const QString className = node->attributeClass();
628     const QString varName = m_driver->findOrInsertWidget(node);
629     m_registeredWidgets.insert(varName, node); // register the current widget
630 
631     QString parentWidget, parentClass;
632     if (m_widgetChain.top()) {
633         parentWidget = m_driver->findOrInsertWidget(m_widgetChain.top());
634         parentClass = m_widgetChain.top()->attributeClass();
635     }
636 
637     const QString savedParentWidget = parentWidget;
638 
639     if (m_uic->isContainer(parentClass) || m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("Q3ToolBar")))
640         parentWidget.clear();
641 
642     if (m_widgetChain.size() != 1)
643         m_output << m_indent << varName << " = new " << m_uic->customWidgetsInfo()->realClassName(className) << '(' << parentWidget << ");\n";
644 
645     parentWidget = savedParentWidget;
646 
647     if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3ComboBox"))) {
648         initializeComboBox3(node);
649     } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QComboBox"))) {
650         initializeComboBox(node);
651     } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QListWidget"))) {
652         initializeListWidget(node);
653     } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTreeWidget"))) {
654         initializeTreeWidget(node);
655     } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTableWidget"))) {
656         initializeTableWidget(node);
657     } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3ListBox"))) {
658         initializeQ3ListBox(node);
659     } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3ListView"))) {
660         initializeQ3ListView(node);
661     } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3IconView"))) {
662         initializeQ3IconView(node);
663     } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3Table"))) {
664         initializeQ3Table(node);
665     } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3DataTable"))) {
666         initializeQ3SqlDataTable(node);
667     } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3DataBrowser"))) {
668         initializeQ3SqlDataBrowser(node);
669     }
670 
671     if (m_uic->isButton(className))
672         addButtonGroup(node, varName);
673 
674     writeProperties(varName, className, node->elementProperty());
675 
676     if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QMenu")) && parentWidget.size()) {
677         initializeMenu(node, parentWidget);
678     }
679 
680     if (node->elementLayout().isEmpty())
681         m_layoutChain.push(0);
682 
683     m_layoutWidget = false;
684     if (className == QLatin1String("QWidget") && !node->hasAttributeNative()) {
685         if (const DomWidget* parentWidget = m_widgetChain.top()) {
686             const QString parentClass = parentWidget->attributeClass();
687             if (parentClass != QLatin1String("QMainWindow")
688                 && !m_uic->isCustomWidgetContainer(parentClass)
689                 && !m_uic->isContainer(parentClass))
690             m_layoutWidget = true;
691         }
692     }
693     m_widgetChain.push(node);
694     m_layoutChain.push(0);
695     TreeWalker::acceptWidget(node);
696     m_layoutChain.pop();
697     m_widgetChain.pop();
698     m_layoutWidget = false;
699 
700     const DomPropertyMap attributes = propertyMap(node->elementAttribute());
701 
702     const QString pageDefaultString = QLatin1String("Page");
703 
704     int id = -1;
705     if (const DomProperty *pid = attributes.value(QLatin1String("id"))) {
706         id = pid->elementNumber();
707     }
708 
709     if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QMainWindow"))
710             || m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("Q3MainWindow"))) {
711 
712         if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QMenuBar"))) {
713             if (!m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("Q3MainWindow")))
714                 m_output << m_indent << parentWidget << "->setMenuBar(" << varName <<");\n";
715         } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QToolBar"))) {
716             m_output << m_indent << parentWidget << "->addToolBar("
717                      << toolBarAreaStringFromDOMAttributes(attributes) << varName << ");\n";
718 
719             if (const DomProperty *pbreak = attributes.value(QLatin1String("toolBarBreak"))) {
720                 if (pbreak->elementBool() == QLatin1String("true")) {
721                     m_output << m_indent << parentWidget << "->insertToolBarBreak(" <<  varName << ");\n";
722                 }
723             }
724 
725         } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QDockWidget"))) {
726             QString area;
727             if (DomProperty *pstyle = attributes.value(QLatin1String("dockWidgetArea"))) {
728                 area += QLatin1String("static_cast<Qt::DockWidgetArea>(");
729                 area += QString::number(pstyle->elementNumber());
730                 area += QLatin1String("), ");
731             }
732 
733             m_output << m_indent << parentWidget << "->addDockWidget(" << area << varName << ");\n";
734         } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QStatusBar"))) {
735             m_output << m_indent << parentWidget << "->setStatusBar(" << varName << ");\n";
736         } else if (!m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3DockWindow"))
737                    && !m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3ToolBar"))) {
738                 m_output << m_indent << parentWidget << "->setCentralWidget(" << varName << ");\n";
739         }
740     }
741 
742     // Check for addPageMethod of a custom plugin first
743     const QString addPageMethod = m_uic->customWidgetsInfo()->customWidgetAddPageMethod(parentClass);
744     if (!addPageMethod.isEmpty()) {
745         m_output << m_indent << parentWidget << "->" << addPageMethod << '(' << varName << ");\n";
746     } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QStackedWidget"))) {
747         m_output << m_indent << parentWidget << "->addWidget(" << varName << ");\n";
748     } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QToolBar"))) {
749         m_output << m_indent << parentWidget << "->addWidget(" << varName << ");\n";
750     } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("Q3WidgetStack"))) {
751         m_output << m_indent << parentWidget << "->addWidget(" << varName << ", " << id << ");\n";
752     } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QDockWidget"))) {
753         m_output << m_indent << parentWidget << "->setWidget(" << varName << ");\n";
754     } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QScrollArea"))) {
755         m_output << m_indent << parentWidget << "->setWidget(" << varName << ");\n";
756     } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QSplitter"))) {
757         m_output << m_indent << parentWidget << "->addWidget(" << varName << ");\n";
758     } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QMdiArea"))) {
759         m_output << m_indent << parentWidget << "->addSubWindow(" << varName << ");\n";
760     } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QWorkspace"))) {
761         m_output << m_indent << parentWidget << "->addWindow(" << varName << ");\n";
762     } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QWizard"))) {
763         addWizardPage(varName, node, parentWidget);
764     } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QToolBox"))) {
765         QString icon;
766         if (const DomProperty *picon = attributes.value(QLatin1String("icon"))) {
767             icon += QLatin1String(", ") ;
768             icon += iconCall(picon);
769         }
770 
771         const DomProperty *plabel = attributes.value(QLatin1String("label"));
772         DomString *plabelString = plabel ? plabel->elementString() : 0;
773 
774         m_output << m_indent << parentWidget << "->addItem(" << varName << icon << ", " << noTrCall(plabelString, pageDefaultString) << ");\n";
775 
776         autoTrOutput(plabelString, pageDefaultString) << m_indent << parentWidget << "->setItemText("
777                    << parentWidget << "->indexOf(" << varName << "), " << autoTrCall(plabelString, pageDefaultString) << ");\n";
778 
779 #ifndef QT_NO_TOOLTIP
780         if (DomProperty *ptoolTip = attributes.value(QLatin1String("toolTip"))) {
781             autoTrOutput(ptoolTip->elementString()) << m_indent << parentWidget << "->setItemToolTip("
782                        << parentWidget << "->indexOf(" << varName << "), " << autoTrCall(ptoolTip->elementString()) << ");\n";
783         }
784 #endif // QT_NO_TOOLTIP
785     } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QTabWidget"))) {
786         QString icon;
787         if (const DomProperty *picon = attributes.value(QLatin1String("icon"))) {
788             icon += QLatin1String(", ");
789             icon += iconCall(picon);
790         }
791 
792         const DomProperty *ptitle = attributes.value(QLatin1String("title"));
793         DomString *ptitleString = ptitle ? ptitle->elementString() : 0;
794 
795         m_output << m_indent << parentWidget << "->addTab(" << varName << icon << ", " << "QString());\n";
796 
797         autoTrOutput(ptitleString, pageDefaultString) << m_indent << parentWidget << "->setTabText("
798                    << parentWidget << "->indexOf(" << varName << "), " << autoTrCall(ptitleString, pageDefaultString) << ");\n";
799 
800 #ifndef QT_NO_TOOLTIP
801         if (const DomProperty *ptoolTip = attributes.value(QLatin1String("toolTip"))) {
802             autoTrOutput(ptoolTip->elementString()) << m_indent << parentWidget << "->setTabToolTip("
803                        << parentWidget << "->indexOf(" << varName << "), " << autoTrCall(ptoolTip->elementString()) << ");\n";
804         }
805 #endif // QT_NO_TOOLTIP
806 #ifndef QT_NO_WHATSTHIS
807         if (const DomProperty *pwhatsThis = attributes.value(QLatin1String("whatsThis"))) {
808             autoTrOutput(pwhatsThis->elementString()) << m_indent << parentWidget << "->setTabWhatsThis("
809                        << parentWidget << "->indexOf(" << varName << "), " << autoTrCall(pwhatsThis->elementString()) << ");\n";
810         }
811 #endif // QT_NO_WHATSTHIS
812     } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("Q3Wizard"))) {
813         const DomProperty *ptitle = attributes.value(QLatin1String("title"));
814         DomString *ptitleString = ptitle ? ptitle->elementString() : 0;
815 
816         m_output << m_indent << parentWidget << "->addPage(" << varName << ", " << noTrCall(ptitleString, pageDefaultString) << ");\n";
817 
818         autoTrOutput(ptitleString, pageDefaultString) << m_indent << parentWidget << "->setTitle("
819                    << varName << ", " << autoTrCall(ptitleString, pageDefaultString) << ");\n";
820 
821     }
822 
823     //
824     // Special handling for qtableview/qtreeview fake header attributes
825     //
826     static QStringList realPropertyNames =
827             (QStringList() << QLatin1String("visible")
828                            << QLatin1String("cascadingSectionResizes")
829                            << QLatin1String("defaultSectionSize")
830                            << QLatin1String("highlightSections")
831                            << QLatin1String("minimumSectionSize")
832                            << QLatin1String("showSortIndicator")
833                            << QLatin1String("stretchLastSection"));
834 
835     if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTreeView"))
836                || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTreeWidget"))) {
837         DomPropertyList headerProperties;
838         foreach (const QString &realPropertyName, realPropertyNames) {
839             const QString upperPropertyName = realPropertyName.at(0).toUpper()
840                                               + realPropertyName.mid(1);
841             const QString fakePropertyName = QLatin1String("header") + upperPropertyName;
842             if (DomProperty *fakeProperty = attributes.value(fakePropertyName)) {
843                 fakeProperty->setAttributeName(realPropertyName);
844                 headerProperties << fakeProperty;
845             }
846         }
847         writeProperties(varName + QLatin1String("->header()"), QLatin1String("QHeaderView"),
848                         headerProperties, WritePropertyIgnoreObjectName);
849 
850     } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTableView"))
851                || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTableWidget"))) {
852 
853         static QStringList headerPrefixes =
854                 (QStringList() << QLatin1String("horizontalHeader")
855                                << QLatin1String("verticalHeader"));
856 
857         foreach (const QString &headerPrefix, headerPrefixes) {
858             DomPropertyList headerProperties;
859             foreach (const QString &realPropertyName, realPropertyNames) {
860                 const QString upperPropertyName = realPropertyName.at(0).toUpper()
861                                                   + realPropertyName.mid(1);
862                 const QString fakePropertyName = headerPrefix + upperPropertyName;
863                 if (DomProperty *fakeProperty = attributes.value(fakePropertyName)) {
864                     fakeProperty->setAttributeName(realPropertyName);
865                     headerProperties << fakeProperty;
866                 }
867             }
868             writeProperties(varName + QLatin1String("->") + headerPrefix + QLatin1String("()"),
869                             QLatin1String("QHeaderView"),
870                             headerProperties, WritePropertyIgnoreObjectName);
871         }
872     }
873 
874     if (node->elementLayout().isEmpty())
875         m_layoutChain.pop();
876 
877     const QStringList zOrder = node->elementZOrder();
878     for (int i = 0; i < zOrder.size(); ++i) {
879         const QString name = zOrder.at(i);
880 
881         if (!m_registeredWidgets.contains(name)) {
882             fprintf(stderr, "%s: Warning: Z-order assignment: '%s' is not a valid widget.\n",
883                     qPrintable(m_option.messagePrefix()),
884                     name.toLatin1().data());
885             continue;
886         }
887 
888         if (name.isEmpty()) {
889             continue;
890         }
891 
892         m_output << m_indent << name << "->raise();\n";
893     }
894 }
895 
addButtonGroup(const DomWidget * buttonNode,const QString & varName)896 void WriteInitialization::addButtonGroup(const DomWidget *buttonNode, const QString &varName)
897 {
898     const DomPropertyMap attributes = propertyMap(buttonNode->elementAttribute());
899     // Look up the button group name as specified in the attribute and find the uniquified name
900     const DomProperty *prop = attributes.value(QLatin1String("buttonGroup"));
901     if (!prop)
902         return;
903     const QString attributeName = toString(prop->elementString());
904     const DomButtonGroup *group = m_driver->findButtonGroup(attributeName);
905     // Legacy feature: Create missing groups on the fly as the UIC button group feature
906     // was present before the actual Designer support (4.5)
907     const bool createGroupOnTheFly = group == 0;
908     if (createGroupOnTheFly) {
909         DomButtonGroup *newGroup = new DomButtonGroup;
910         newGroup->setAttributeName(attributeName);
911         group = newGroup;
912         fprintf(stderr, "%s: Warning: Creating button group `%s'\n",
913                 qPrintable(m_option.messagePrefix()),
914                 attributeName.toLatin1().data());
915     }
916     const QString groupName = m_driver->findOrInsertButtonGroup(group);
917     // Create on demand
918     if (!m_buttonGroups.contains(groupName)) {
919         const QString className = QLatin1String("QButtonGroup");
920         m_output << m_indent;
921         if (createGroupOnTheFly)
922             m_output << className << " *";
923         m_output << groupName << " = new " << className << '(' << m_mainFormVarName << ");\n";
924         m_buttonGroups.insert(groupName);
925         writeProperties(groupName, className, group->elementProperty());
926     }
927     m_output << m_indent << groupName << "->addButton(" << varName << ");\n";
928 }
929 
acceptLayout(DomLayout * node)930 void WriteInitialization::acceptLayout(DomLayout *node)
931 {
932     const QString className = node->attributeClass();
933     const QString varName = m_driver->findOrInsertLayout(node);
934 
935     const DomPropertyMap properties = propertyMap(node->elementProperty());
936     const bool oldLayoutProperties = properties.constFind(QLatin1String("margin")) != properties.constEnd();
937 
938     bool isGroupBox = false;
939 
940     if (m_widgetChain.top()) {
941         const QString parentWidget = m_widgetChain.top()->attributeClass();
942 
943         if (!m_layoutChain.top() && (m_uic->customWidgetsInfo()->extends(parentWidget, QLatin1String("Q3GroupBox"))
944                         || m_uic->customWidgetsInfo()->extends(parentWidget, QLatin1String("Q3ButtonGroup")))) {
945             const QString parent = m_driver->findOrInsertWidget(m_widgetChain.top());
946 
947             isGroupBox = true;
948             // special case for group box
949 
950             m_output << m_indent << parent << "->setColumnLayout(0, Qt::Vertical);\n";
951             QString objectName = parent;
952             objectName += QLatin1String("->layout()");
953             int marginType = Use43UiFile;
954             if (oldLayoutProperties)
955                 marginType = m_layoutMarginType;
956 
957             m_LayoutDefaultHandler.writeProperties(m_indent,
958                                     objectName, properties, marginType, false, m_output);
959         }
960     }
961 
962     m_output << m_indent << varName << " = new " << className << '(';
963 
964     if (!m_layoutChain.top() && !isGroupBox)
965         m_output << m_driver->findOrInsertWidget(m_widgetChain.top());
966 
967     m_output << ");\n";
968 
969     if (isGroupBox) {
970         const QString tempName = m_driver->unique(QLatin1String("boxlayout"));
971         m_output << m_indent << "QBoxLayout *" << tempName << " = qobject_cast<QBoxLayout *>(" <<
972                     m_driver->findOrInsertWidget(m_widgetChain.top()) << "->layout());\n";
973         m_output << m_indent << "if (" << tempName << ")\n";
974         m_output << m_dindent << tempName << "->addLayout(" << varName << ");\n";
975     }
976 
977     if (isGroupBox) {
978         m_output << m_indent << varName << "->setAlignment(Qt::AlignTop);\n";
979     }  else {
980         // Suppress margin on a read child layout
981         const bool suppressMarginDefault = m_layoutChain.top();
982         int marginType = Use43UiFile;
983         if (oldLayoutProperties)
984             marginType = m_layoutMarginType;
985         m_LayoutDefaultHandler.writeProperties(m_indent, varName, properties, marginType, suppressMarginDefault, m_output);
986     }
987 
988     m_layoutMarginType = SubLayoutMargin;
989 
990     DomPropertyList propList = node->elementProperty();
991     if (m_layoutWidget) {
992         bool left, top, right, bottom;
993         left = top = right = bottom = false;
994         for (int i = 0; i < propList.size(); ++i) {
995             const DomProperty *p = propList.at(i);
996             const QString propertyName = p->attributeName();
997             if (propertyName == QLatin1String("leftMargin") && p->kind() == DomProperty::Number)
998                 left = true;
999             else if (propertyName == QLatin1String("topMargin") && p->kind() == DomProperty::Number)
1000                 top = true;
1001             else if (propertyName == QLatin1String("rightMargin") && p->kind() == DomProperty::Number)
1002                 right = true;
1003             else if (propertyName == QLatin1String("bottomMargin") && p->kind() == DomProperty::Number)
1004                 bottom = true;
1005         }
1006         if (!left) {
1007             DomProperty *p = new DomProperty();
1008             p->setAttributeName(QLatin1String("leftMargin"));
1009             p->setElementNumber(0);
1010             propList.append(p);
1011         }
1012         if (!top) {
1013             DomProperty *p = new DomProperty();
1014             p->setAttributeName(QLatin1String("topMargin"));
1015             p->setElementNumber(0);
1016             propList.append(p);
1017         }
1018         if (!right) {
1019             DomProperty *p = new DomProperty();
1020             p->setAttributeName(QLatin1String("rightMargin"));
1021             p->setElementNumber(0);
1022             propList.append(p);
1023         }
1024         if (!bottom) {
1025             DomProperty *p = new DomProperty();
1026             p->setAttributeName(QLatin1String("bottomMargin"));
1027             p->setElementNumber(0);
1028             propList.append(p);
1029         }
1030         m_layoutWidget = false;
1031     }
1032 
1033     writeProperties(varName, className, propList, WritePropertyIgnoreMargin|WritePropertyIgnoreSpacing);
1034 
1035     m_layoutChain.push(node);
1036     TreeWalker::acceptLayout(node);
1037     m_layoutChain.pop();
1038 
1039     // Stretch? (Unless we are compiling for UIC3)
1040     const QString numberNull = QString(QLatin1Char('0'));
1041     writePropertyList(varName, QLatin1String("setStretch"), node->attributeStretch(), numberNull);
1042     writePropertyList(varName, QLatin1String("setRowStretch"), node->attributeRowStretch(), numberNull);
1043     writePropertyList(varName, QLatin1String("setColumnStretch"), node->attributeColumnStretch(), numberNull);
1044     writePropertyList(varName, QLatin1String("setColumnMinimumWidth"), node->attributeColumnMinimumWidth(), numberNull);
1045     writePropertyList(varName, QLatin1String("setRowMinimumHeight"), node->attributeRowMinimumHeight(), numberNull);
1046 }
1047 
1048 // Apply a comma-separated list of values using a function "setSomething(int idx, value)"
writePropertyList(const QString & varName,const QString & setFunction,const QString & value,const QString & defaultValue)1049 void WriteInitialization::writePropertyList(const QString &varName,
1050                                             const QString &setFunction,
1051                                             const QString &value,
1052                                             const QString &defaultValue)
1053 {
1054     if (value.isEmpty())
1055         return;
1056     const QStringList list = value.split(QLatin1Char(','));
1057     const int count =  list.count();
1058     for (int i = 0; i < count; i++)
1059         if (list.at(i) != defaultValue)
1060             m_output << m_indent << varName << "->" << setFunction << '(' << i << ", " << list.at(i) << ");\n";
1061 }
1062 
acceptSpacer(DomSpacer * node)1063 void WriteInitialization::acceptSpacer(DomSpacer *node)
1064 {
1065     m_output << m_indent << m_driver->findOrInsertSpacer(node) << " = ";
1066     writeSpacerItem(node, m_output);
1067     m_output << ";\n";
1068 }
1069 
formLayoutRole(int column,int colspan)1070 static inline QString formLayoutRole(int column, int colspan)
1071 {
1072     if (colspan > 1)
1073         return QLatin1String("QFormLayout::SpanningRole");
1074     return column == 0 ? QLatin1String("QFormLayout::LabelRole") : QLatin1String("QFormLayout::FieldRole");
1075 }
1076 
acceptLayoutItem(DomLayoutItem * node)1077 void WriteInitialization::acceptLayoutItem(DomLayoutItem *node)
1078 {
1079     TreeWalker::acceptLayoutItem(node);
1080 
1081     DomLayout *layout = m_layoutChain.top();
1082 
1083     if (!layout)
1084         return;
1085 
1086     const QString layoutName = m_driver->findOrInsertLayout(layout);
1087     const QString itemName = m_driver->findOrInsertLayoutItem(node);
1088 
1089     QString addArgs;
1090     QString methodPrefix = QLatin1String("add"); //Consistent API-design galore!
1091     if (layout->attributeClass() == QLatin1String("QGridLayout")) {
1092         const int row = node->attributeRow();
1093         const int col = node->attributeColumn();
1094 
1095         const int rowSpan = node->hasAttributeRowSpan() ? node->attributeRowSpan() : 1;
1096         const int colSpan = node->hasAttributeColSpan() ? node->attributeColSpan() : 1;
1097 
1098         addArgs = QString::fromLatin1("%1, %2, %3, %4, %5").arg(itemName).arg(row).arg(col).arg(rowSpan).arg(colSpan);
1099         if (!node->attributeAlignment().isEmpty())
1100             addArgs += QLatin1String(", ") + node->attributeAlignment();
1101     } else {
1102         if (layout->attributeClass() == QLatin1String("QFormLayout")) {
1103             methodPrefix = QLatin1String("set");
1104             const int row = node->attributeRow();
1105             const int colSpan = node->hasAttributeColSpan() ? node->attributeColSpan() : 1;
1106             const QString role = formLayoutRole(node->attributeColumn(), colSpan);
1107             addArgs = QString::fromLatin1("%1, %2, %3").arg(row).arg(role).arg(itemName);
1108         } else {
1109             addArgs = itemName;
1110             if (layout->attributeClass().contains(QLatin1String("Box")) && !node->attributeAlignment().isEmpty())
1111                 addArgs += QLatin1String(", 0, ") + node->attributeAlignment();
1112         }
1113     }
1114 
1115     // figure out "add" method
1116     m_output << "\n" << m_indent << layoutName << "->";
1117     switch (node->kind()) {
1118     case DomLayoutItem::Widget:
1119         m_output << methodPrefix << "Widget(" <<  addArgs;
1120         break;
1121     case DomLayoutItem::Layout:
1122         m_output <<  methodPrefix << "Layout(" << addArgs;
1123         break;
1124     case DomLayoutItem::Spacer:
1125         m_output << methodPrefix << "Item(" << addArgs;
1126         break;
1127     case DomLayoutItem::Unknown:
1128         Q_ASSERT( 0 );
1129         break;
1130     }
1131     m_output << ");\n\n";
1132 }
1133 
acceptActionGroup(DomActionGroup * node)1134 void WriteInitialization::acceptActionGroup(DomActionGroup *node)
1135 {
1136     const QString actionName = m_driver->findOrInsertActionGroup(node);
1137     QString varName = m_driver->findOrInsertWidget(m_widgetChain.top());
1138 
1139     if (m_actionGroupChain.top())
1140         varName = m_driver->findOrInsertActionGroup(m_actionGroupChain.top());
1141 
1142     m_output << m_indent << actionName << " = new QActionGroup(" << varName << ");\n";
1143     writeProperties(actionName, QLatin1String("QActionGroup"), node->elementProperty());
1144 
1145     m_actionGroupChain.push(node);
1146     TreeWalker::acceptActionGroup(node);
1147     m_actionGroupChain.pop();
1148 }
1149 
acceptAction(DomAction * node)1150 void WriteInitialization::acceptAction(DomAction *node)
1151 {
1152     if (node->hasAttributeMenu())
1153         return;
1154 
1155     const QString actionName = m_driver->findOrInsertAction(node);
1156     m_registeredActions.insert(actionName, node);
1157     QString varName = m_driver->findOrInsertWidget(m_widgetChain.top());
1158 
1159     if (m_actionGroupChain.top())
1160         varName = m_driver->findOrInsertActionGroup(m_actionGroupChain.top());
1161 
1162     m_output << m_indent << actionName << " = new QAction(" << varName << ");\n";
1163     writeProperties(actionName, QLatin1String("QAction"), node->elementProperty());
1164 }
1165 
acceptActionRef(DomActionRef * node)1166 void WriteInitialization::acceptActionRef(DomActionRef *node)
1167 {
1168     QString actionName = node->attributeName();
1169     const bool isSeparator = actionName == QLatin1String("separator");
1170     bool isMenu = false;
1171 
1172     QString varName = m_driver->findOrInsertWidget(m_widgetChain.top());
1173 
1174     if (actionName.isEmpty() || !m_widgetChain.top()) {
1175         return;
1176     } else if (m_driver->actionGroupByName(actionName)) {
1177         return;
1178     } else if (DomWidget *w = m_driver->widgetByName(actionName)) {
1179         isMenu = m_uic->isMenu(w->attributeClass());
1180         bool inQ3ToolBar = m_uic->customWidgetsInfo()->extends(m_widgetChain.top()->attributeClass(), QLatin1String("Q3ToolBar"));
1181         if (!isMenu && inQ3ToolBar) {
1182             m_actionOut << m_indent << actionName << "->setParent(" << varName << ");\n";
1183             return;
1184         }
1185     } else if (!(m_driver->actionByName(actionName) || isSeparator)) {
1186         fprintf(stderr, "%s: Warning: action `%s' not declared\n",
1187                 qPrintable(m_option.messagePrefix()),
1188                 actionName.toLatin1().data());
1189         return;
1190     }
1191 
1192     if (m_widgetChain.top() && isSeparator) {
1193         // separator is always reserved!
1194         m_actionOut << m_indent << varName << "->addSeparator();\n";
1195         return;
1196     }
1197 
1198     if (isMenu)
1199         actionName += QLatin1String("->menuAction()");
1200 
1201     m_actionOut << m_indent << varName << "->addAction(" << actionName << ");\n";
1202 }
1203 
writeProperties(const QString & varName,const QString & className,const DomPropertyList & lst,unsigned flags)1204 void WriteInitialization::writeProperties(const QString &varName,
1205                                           const QString &className,
1206                                           const DomPropertyList &lst,
1207                                           unsigned flags)
1208 {
1209     const bool isTopLevel = m_widgetChain.count() == 1;
1210 
1211     if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QAxWidget"))) {
1212         DomPropertyMap properties = propertyMap(lst);
1213         if (properties.contains(QLatin1String("control"))) {
1214             DomProperty *p = properties.value(QLatin1String("control"));
1215             m_output << m_indent << varName << "->setControl(QString::fromUtf8("
1216                    << fixString(toString(p->elementString()), m_dindent) << "));\n";
1217         }
1218     }
1219 
1220     DomWidget *buttonGroupWidget = findWidget(QLatin1String("Q3ButtonGroup"));
1221 
1222     QString indent;
1223     if (!m_widgetChain.top()) {
1224         indent = m_option.indent;
1225         m_output << m_indent << "if (" << varName << "->objectName().isEmpty())\n";
1226     }
1227     if (!(flags & WritePropertyIgnoreObjectName))
1228         m_output << m_indent << indent << varName
1229                 << "->setObjectName(QString::fromUtf8(" << fixString(varName, m_dindent) << "));\n";
1230 
1231     int leftMargin, topMargin, rightMargin, bottomMargin;
1232     leftMargin = topMargin = rightMargin = bottomMargin = -1;
1233     bool frameShadowEncountered = false;
1234 
1235     for (int i=0; i<lst.size(); ++i) {
1236         const DomProperty *p = lst.at(i);
1237         if (!checkProperty(m_option.inputFile, p))
1238             continue;
1239         const QString propertyName = p->attributeName();
1240         QString propertyValue;
1241 
1242         // special case for the property `geometry': Do not use position
1243         if (isTopLevel && propertyName == QLatin1String("geometry") && p->elementRect()) {
1244             const DomRect *r = p->elementRect();
1245             m_output << m_indent << varName << "->resize(" << r->elementWidth() << ", " << r->elementHeight() << ");\n";
1246             continue;
1247         } else if (propertyName == QLatin1String("buttonGroupId")) { // Q3ButtonGroup support
1248             if (buttonGroupWidget)
1249                 m_output << m_indent << m_driver->findOrInsertWidget(buttonGroupWidget) << "->insert("
1250                          << varName << ", " << p->elementNumber() << ");\n";
1251             continue;
1252         } else if (propertyName == QLatin1String("currentRow") // QListWidget::currentRow
1253                     && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QListWidget"))) {
1254             m_delayedOut << m_indent << varName << "->setCurrentRow("
1255                        << p->elementNumber() << ");\n";
1256             continue;
1257         } else if (propertyName == QLatin1String("currentIndex") // set currentIndex later
1258                     && (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QComboBox"))
1259                     || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QStackedWidget"))
1260                     || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTabWidget"))
1261                     || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QToolBox")))) {
1262             m_delayedOut << m_indent << varName << "->setCurrentIndex("
1263                        << p->elementNumber() << ");\n";
1264             continue;
1265         } else if (propertyName == QLatin1String("tabSpacing")
1266                     && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QToolBox"))) {
1267             m_delayedOut << m_indent << varName << "->layout()->setSpacing("
1268                        << p->elementNumber() << ");\n";
1269             continue;
1270         } else if (propertyName == QLatin1String("control") // ActiveQt support
1271                     && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QAxWidget"))) {
1272             // already done ;)
1273             continue;
1274         } else if (propertyName == QLatin1String("database")
1275                     && p->elementStringList()) {
1276             // Sql support
1277             continue;
1278         } else if (propertyName == QLatin1String("frameworkCode")
1279                     && p->kind() == DomProperty::Bool) {
1280             // Sql support
1281             continue;
1282         } else if (propertyName == QLatin1String("orientation")
1283                     && m_uic->customWidgetsInfo()->extends(className, QLatin1String("Line"))) {
1284             // Line support
1285             QString shape = QLatin1String("QFrame::HLine");
1286             if (p->elementEnum() == QLatin1String("Qt::Vertical"))
1287                 shape = QLatin1String("QFrame::VLine");
1288 
1289             m_output << m_indent << varName << "->setFrameShape(" << shape << ");\n";
1290             // QFrame Default is 'Plain'. Make the line 'Sunken' unless otherwise specified
1291             if (!frameShadowEncountered)
1292                 m_output << m_indent << varName << "->setFrameShadow(QFrame::Sunken);\n";
1293             continue;
1294         } else if ((flags & WritePropertyIgnoreMargin)  && propertyName == QLatin1String("margin")) {
1295             continue;
1296         } else if ((flags & WritePropertyIgnoreSpacing) && propertyName == QLatin1String("spacing")) {
1297             continue;
1298         } else if (propertyName == QLatin1String("leftMargin") && p->kind() == DomProperty::Number) {
1299             leftMargin = p->elementNumber();
1300             continue;
1301         } else if (propertyName == QLatin1String("topMargin") && p->kind() == DomProperty::Number) {
1302             topMargin = p->elementNumber();
1303             continue;
1304         } else if (propertyName == QLatin1String("rightMargin") && p->kind() == DomProperty::Number) {
1305             rightMargin = p->elementNumber();
1306             continue;
1307         } else if (propertyName == QLatin1String("bottomMargin") && p->kind() == DomProperty::Number) {
1308             bottomMargin = p->elementNumber();
1309             continue;
1310         } else if (propertyName == QLatin1String("frameShadow"))
1311             frameShadowEncountered = true;
1312 
1313         bool stdset = m_stdsetdef;
1314         if (p->hasAttributeStdset())
1315             stdset = p->attributeStdset();
1316 
1317         QString setFunction;
1318 
1319         if (stdset) {
1320             setFunction = QLatin1String("->set");
1321             setFunction += propertyName.left(1).toUpper();
1322             setFunction += propertyName.mid(1);
1323             setFunction += QLatin1Char('(');
1324         } else {
1325             setFunction = QLatin1String("->setProperty(\"");
1326             setFunction += propertyName;
1327             setFunction += QLatin1String("\", QVariant(");
1328         }
1329 
1330         QString varNewName = varName;
1331 
1332         switch (p->kind()) {
1333         case DomProperty::Bool: {
1334             propertyValue = p->elementBool();
1335             break;
1336         }
1337         case DomProperty::Color:
1338             propertyValue = domColor2QString(p->elementColor());
1339             break;
1340         case DomProperty::Cstring:
1341             if (propertyName == QLatin1String("buddy") && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QLabel"))) {
1342                 m_buddies.append(Buddy(varName, p->elementCstring()));
1343             } else {
1344                 if (stdset)
1345                     propertyValue = fixString(p->elementCstring(), m_dindent);
1346                 else {
1347                     propertyValue = QLatin1String("QByteArray(");
1348                     propertyValue += fixString(p->elementCstring(), m_dindent);
1349                     propertyValue += QLatin1Char(')');
1350                 }
1351             }
1352             break;
1353         case DomProperty::Cursor:
1354             propertyValue = QString::fromLatin1("QCursor(static_cast<Qt::CursorShape>(%1))")
1355                             .arg(p->elementCursor());
1356             break;
1357         case DomProperty::CursorShape:
1358             if (p->hasAttributeStdset() && !p->attributeStdset())
1359                 varNewName += QLatin1String("->viewport()");
1360             propertyValue = QString::fromLatin1("QCursor(Qt::%1)")
1361                             .arg(p->elementCursorShape());
1362             break;
1363         case DomProperty::Enum:
1364             propertyValue = p->elementEnum();
1365             if (!propertyValue.contains(QLatin1String("::"))) {
1366                 QString scope  = className;
1367                 scope += QLatin1String("::");
1368                 propertyValue.prepend(scope);
1369             }
1370             break;
1371         case DomProperty::Set:
1372             propertyValue = p->elementSet();
1373             break;
1374         case DomProperty::Font:
1375             propertyValue = writeFontProperties(p->elementFont());
1376             break;
1377         case DomProperty::IconSet:
1378             propertyValue = writeIconProperties(p->elementIconSet());
1379             break;
1380         case DomProperty::Pixmap:
1381             propertyValue = pixCall(p);
1382             break;
1383         case DomProperty::Palette: {
1384             const DomPalette *pal = p->elementPalette();
1385             const QString paletteName = m_driver->unique(QLatin1String("palette"));
1386             m_output << m_indent << "QPalette " << paletteName << ";\n";
1387 
1388             writeColorGroup(pal->elementActive(), QLatin1String("QPalette::Active"), paletteName);
1389             writeColorGroup(pal->elementInactive(), QLatin1String("QPalette::Inactive"), paletteName);
1390             writeColorGroup(pal->elementDisabled(), QLatin1String("QPalette::Disabled"), paletteName);
1391 
1392             propertyValue = paletteName;
1393             break;
1394         }
1395         case DomProperty::Point: {
1396             const DomPoint *po = p->elementPoint();
1397             propertyValue = QString::fromLatin1("QPoint(%1, %2)")
1398                             .arg(po->elementX()).arg(po->elementY());
1399             break;
1400         }
1401         case DomProperty::PointF: {
1402             const DomPointF *pof = p->elementPointF();
1403             propertyValue = QString::fromLatin1("QPointF(%1, %2)")
1404                             .arg(pof->elementX()).arg(pof->elementY());
1405             break;
1406         }
1407         case DomProperty::Rect: {
1408             const DomRect *r = p->elementRect();
1409             propertyValue = QString::fromLatin1("QRect(%1, %2, %3, %4)")
1410                             .arg(r->elementX()).arg(r->elementY())
1411                             .arg(r->elementWidth()).arg(r->elementHeight());
1412             break;
1413         }
1414         case DomProperty::RectF: {
1415             const DomRectF *rf = p->elementRectF();
1416             propertyValue = QString::fromLatin1("QRectF(%1, %2, %3, %4)")
1417                             .arg(rf->elementX()).arg(rf->elementY())
1418                             .arg(rf->elementWidth()).arg(rf->elementHeight());
1419             break;
1420         }
1421         case DomProperty::Locale: {
1422              const DomLocale *locale = p->elementLocale();
1423              propertyValue = QString::fromLatin1("QLocale(QLocale::%1, QLocale::%2)")
1424                              .arg(locale->attributeLanguage()).arg(locale->attributeCountry());
1425             break;
1426         }
1427         case DomProperty::SizePolicy: {
1428             const QString spName = writeSizePolicy( p->elementSizePolicy());
1429             m_output << m_indent << spName << QString::fromLatin1(
1430                 ".setHeightForWidth(%1->sizePolicy().hasHeightForWidth());\n")
1431                 .arg(varName);
1432 
1433             propertyValue = spName;
1434             break;
1435         }
1436         case DomProperty::Size: {
1437              const DomSize *s = p->elementSize();
1438               propertyValue = QString::fromLatin1("QSize(%1, %2)")
1439                              .arg(s->elementWidth()).arg(s->elementHeight());
1440             break;
1441         }
1442         case DomProperty::SizeF: {
1443             const DomSizeF *sf = p->elementSizeF();
1444              propertyValue = QString::fromLatin1("QSizeF(%1, %2)")
1445                             .arg(sf->elementWidth()).arg(sf->elementHeight());
1446             break;
1447         }
1448         case DomProperty::String: {
1449             if (propertyName == QLatin1String("objectName")) {
1450                 const QString v = p->elementString()->text();
1451                 if (v == varName)
1452                     break;
1453 
1454                 // ### qWarning("Deprecated: the property `objectName' is different from the variable name");
1455             }
1456 
1457             propertyValue = autoTrCall(p->elementString());
1458             break;
1459         }
1460         case DomProperty::Number:
1461             propertyValue = QString::number(p->elementNumber());
1462             break;
1463         case DomProperty::UInt:
1464             propertyValue = QString::number(p->elementUInt());
1465             propertyValue += QLatin1Char('u');
1466             break;
1467         case DomProperty::LongLong:
1468             propertyValue = QLatin1String("Q_INT64_C(");
1469             propertyValue += QString::number(p->elementLongLong());
1470             propertyValue += QLatin1Char(')');;
1471             break;
1472         case DomProperty::ULongLong:
1473             propertyValue = QLatin1String("Q_UINT64_C(");
1474             propertyValue += QString::number(p->elementULongLong());
1475             propertyValue += QLatin1Char(')');
1476             break;
1477         case DomProperty::Float:
1478             propertyValue = QString::number(p->elementFloat());
1479             break;
1480         case DomProperty::Double:
1481             propertyValue = QString::number(p->elementDouble());
1482             break;
1483         case DomProperty::Char: {
1484             const DomChar *c = p->elementChar();
1485             propertyValue = QString::fromLatin1("QChar(%1)")
1486                             .arg(c->elementUnicode());
1487             break;
1488         }
1489         case DomProperty::Date: {
1490             const DomDate *d = p->elementDate();
1491             propertyValue = QString::fromLatin1("QDate(%1, %2, %3)")
1492                             .arg(d->elementYear())
1493                             .arg(d->elementMonth())
1494                             .arg(d->elementDay());
1495             break;
1496         }
1497         case DomProperty::Time: {
1498             const DomTime *t = p->elementTime();
1499             propertyValue = QString::fromLatin1("QTime(%1, %2, %3)")
1500                             .arg(t->elementHour())
1501                             .arg(t->elementMinute())
1502                             .arg(t->elementSecond());
1503             break;
1504         }
1505         case DomProperty::DateTime: {
1506             const DomDateTime *dt = p->elementDateTime();
1507             propertyValue = QString::fromLatin1("QDateTime(QDate(%1, %2, %3), QTime(%4, %5, %6))")
1508                             .arg(dt->elementYear())
1509                             .arg(dt->elementMonth())
1510                             .arg(dt->elementDay())
1511                             .arg(dt->elementHour())
1512                             .arg(dt->elementMinute())
1513                             .arg(dt->elementSecond());
1514             break;
1515         }
1516         case DomProperty::StringList:
1517             propertyValue = QLatin1String("QStringList()");
1518             if (p->elementStringList()->elementString().size()) {
1519                 const QStringList lst = p->elementStringList()->elementString();
1520                 for (int i=0; i<lst.size(); ++i) {
1521                     propertyValue += QLatin1String(" << QString::fromUtf8(");
1522                     propertyValue += fixString(lst.at(i), m_dindent);
1523                     propertyValue += QLatin1Char(')');
1524                 }
1525             }
1526             break;
1527 
1528         case DomProperty::Url: {
1529             const DomUrl* u = p->elementUrl();
1530             propertyValue = QString::fromLatin1("QUrl(QString::fromUtf8(%1))")
1531                             .arg(fixString(u->elementString()->text(), m_dindent));
1532             break;
1533         }
1534         case DomProperty::Brush:
1535             propertyValue = writeBrushInitialization(p->elementBrush());
1536             break;
1537         case DomProperty::Unknown:
1538             break;
1539         }
1540 
1541         if (propertyValue.size()) {
1542             const char* defineC = 0;
1543             if (propertyName == QLatin1String("toolTip"))
1544                 defineC = toolTipDefineC;
1545             else if (propertyName == QLatin1String("whatsThis"))
1546                 defineC = whatsThisDefineC;
1547             else if (propertyName == QLatin1String("statusTip"))
1548                 defineC = statusTipDefineC;
1549             else if (propertyName == QLatin1String("accessibleName") || propertyName == QLatin1String("accessibleDescription"))
1550                 defineC = accessibilityDefineC;
1551 
1552             QTextStream &o = autoTrOutput(p->elementString());
1553 
1554             if (defineC)
1555                 openIfndef(o, QLatin1String(defineC));
1556             o << m_indent << varNewName << setFunction << propertyValue;
1557             if (!stdset)
1558                 o << ')';
1559             o << ");\n";
1560             if (defineC)
1561                 closeIfndef(o, QLatin1String(defineC));
1562 
1563             if (varName == m_mainFormVarName && &o == &m_refreshOut) {
1564                 // this is the only place (currently) where we output mainForm name to the retranslateUi().
1565                 // Other places output merely instances of a certain class (which cannot be main form, e.g. QListWidget).
1566                 m_mainFormUsedInRetranslateUi = true;
1567             }
1568         }
1569     }
1570     if (leftMargin != -1 || topMargin != -1 || rightMargin != -1 || bottomMargin != -1) {
1571         QString objectName = varName;
1572         if (m_widgetChain.top()) {
1573             const QString parentWidget = m_widgetChain.top()->attributeClass();
1574 
1575             if (!m_layoutChain.top() && (m_uic->customWidgetsInfo()->extends(parentWidget, QLatin1String("Q3GroupBox"))
1576                         || m_uic->customWidgetsInfo()->extends(parentWidget, QLatin1String("Q3ButtonGroup")))) {
1577                 objectName = m_driver->findOrInsertWidget(m_widgetChain.top()) + QLatin1String("->layout()");
1578             }
1579         }
1580         m_output << m_indent << objectName << QLatin1String("->setContentsMargins(")
1581                  << leftMargin << QLatin1String(", ")
1582                  << topMargin << QLatin1String(", ")
1583                  << rightMargin << QLatin1String(", ")
1584                  << bottomMargin << QLatin1String(");\n");
1585     }
1586 }
1587 
writeSizePolicy(const DomSizePolicy * sp)1588 QString  WriteInitialization::writeSizePolicy(const DomSizePolicy *sp)
1589 {
1590 
1591     // check cache
1592     const SizePolicyHandle sizePolicyHandle(sp);
1593     const SizePolicyNameMap::const_iterator it = m_sizePolicyNameMap.constFind(sizePolicyHandle);
1594     if ( it != m_sizePolicyNameMap.constEnd()) {
1595         return it.value();
1596     }
1597 
1598 
1599     // insert with new name
1600     const QString spName = m_driver->unique(QLatin1String("sizePolicy"));
1601     m_sizePolicyNameMap.insert(sizePolicyHandle, spName);
1602 
1603     m_output << m_indent << "QSizePolicy " << spName;
1604     do {
1605         if (sp->hasElementHSizeType() && sp->hasElementVSizeType()) {
1606             m_output << "(static_cast<QSizePolicy::Policy>(" << sp->elementHSizeType()
1607                 << "), static_cast<QSizePolicy::Policy>(" << sp->elementVSizeType() << "));\n";
1608             break;
1609         }
1610         if (sp->hasAttributeHSizeType() && sp->hasAttributeVSizeType()) {
1611                 m_output << "(QSizePolicy::" << sp->attributeHSizeType() << ", QSizePolicy::"
1612                 << sp->attributeVSizeType() << ");\n";
1613             break;
1614         }
1615         m_output << ";\n";
1616     } while (false);
1617 
1618     m_output << m_indent << spName << ".setHorizontalStretch("
1619         << sp->elementHorStretch() << ");\n";
1620     m_output << m_indent << spName << ".setVerticalStretch("
1621         << sp->elementVerStretch() << ");\n";
1622     return spName;
1623 }
1624 // Check for a font with the given properties in the FontPropertiesNameMap
1625 // or create a new one. Returns the name.
1626 
writeFontProperties(const DomFont * f)1627 QString WriteInitialization::writeFontProperties(const DomFont *f)
1628 {
1629     // check cache
1630     const FontHandle fontHandle(f);
1631     const FontPropertiesNameMap::const_iterator it = m_fontPropertiesNameMap.constFind(fontHandle);
1632     if ( it != m_fontPropertiesNameMap.constEnd()) {
1633         return it.value();
1634     }
1635 
1636     // insert with new name
1637     const QString fontName = m_driver->unique(QLatin1String("font"));
1638     m_fontPropertiesNameMap.insert(FontHandle(f), fontName);
1639 
1640     m_output << m_indent << "QFont " << fontName << ";\n";
1641     if (f->hasElementFamily() && !f->elementFamily().isEmpty()) {
1642         m_output << m_indent << fontName << ".setFamily(QString::fromUtf8(" << fixString(f->elementFamily(), m_dindent)
1643             << "));\n";
1644     }
1645     if (f->hasElementPointSize() && f->elementPointSize() > 0) {
1646          m_output << m_indent << fontName << ".setPointSize(" << f->elementPointSize()
1647              << ");\n";
1648     }
1649 
1650     if (f->hasElementBold()) {
1651         m_output << m_indent << fontName << ".setBold("
1652             << (f->elementBold() ? "true" : "false") << ");\n";
1653     }
1654     if (f->hasElementItalic()) {
1655         m_output << m_indent << fontName << ".setItalic("
1656             <<  (f->elementItalic() ? "true" : "false") << ");\n";
1657     }
1658     if (f->hasElementUnderline()) {
1659         m_output << m_indent << fontName << ".setUnderline("
1660             << (f->elementUnderline() ? "true" : "false") << ");\n";
1661     }
1662     if (f->hasElementWeight() && f->elementWeight() > 0) {
1663         m_output << m_indent << fontName << ".setWeight("
1664             << f->elementWeight() << ");" << endl;
1665     }
1666     if (f->hasElementStrikeOut()) {
1667          m_output << m_indent << fontName << ".setStrikeOut("
1668             << (f->elementStrikeOut() ? "true" : "false") << ");\n";
1669     }
1670     if (f->hasElementKerning()) {
1671         m_output << m_indent << fontName << ".setKerning("
1672             << (f->elementKerning() ? "true" : "false") << ");\n";
1673     }
1674     if (f->hasElementAntialiasing()) {
1675         m_output << m_indent << fontName << ".setStyleStrategy("
1676             << (f->elementAntialiasing() ? "QFont::PreferDefault" : "QFont::NoAntialias") << ");\n";
1677     }
1678     if (f->hasElementStyleStrategy()) {
1679          m_output << m_indent << fontName << ".setStyleStrategy(QFont::"
1680             << f->elementStyleStrategy() << ");\n";
1681     }
1682     return  fontName;
1683 }
1684 
1685 // Post 4.4 write resource icon
writeResourceIcon(QTextStream & output,const QString & iconName,const QString & indent,const DomResourceIcon * i)1686 static void writeResourceIcon(QTextStream &output,
1687                               const QString &iconName,
1688                               const QString &indent,
1689                               const DomResourceIcon *i)
1690 {
1691     if (i->hasElementNormalOff())
1692         output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementNormalOff()->text(), indent) << "), QSize(), QIcon::Normal, QIcon::Off);\n";
1693     if (i->hasElementNormalOn())
1694         output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementNormalOn()->text(), indent) << "), QSize(), QIcon::Normal, QIcon::On);\n";
1695     if (i->hasElementDisabledOff())
1696         output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementDisabledOff()->text(), indent) << "), QSize(), QIcon::Disabled, QIcon::Off);\n";
1697     if (i->hasElementDisabledOn())
1698         output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementDisabledOn()->text(), indent) << "), QSize(), QIcon::Disabled, QIcon::On);\n";
1699     if (i->hasElementActiveOff())
1700         output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementActiveOff()->text(), indent) << "), QSize(), QIcon::Active, QIcon::Off);\n";
1701     if (i->hasElementActiveOn())
1702         output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementActiveOn()->text(), indent) << "), QSize(), QIcon::Active, QIcon::On);\n";
1703     if (i->hasElementSelectedOff())
1704         output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementSelectedOff()->text(), indent) << "), QSize(), QIcon::Selected, QIcon::Off);\n";
1705     if (i->hasElementSelectedOn())
1706         output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementSelectedOn()->text(), indent) << "), QSize(), QIcon::Selected, QIcon::On);\n";
1707 }
1708 
writeIconProperties(const DomResourceIcon * i)1709 QString WriteInitialization::writeIconProperties(const DomResourceIcon *i)
1710 {
1711     // check cache
1712     const IconHandle iconHandle(i);
1713     const IconPropertiesNameMap::const_iterator it = m_iconPropertiesNameMap.constFind(iconHandle);
1714     if (it != m_iconPropertiesNameMap.constEnd()) {
1715         return it.value();
1716     }
1717 
1718     // insert with new name
1719     const QString iconName = m_driver->unique(QLatin1String("icon"));
1720     m_iconPropertiesNameMap.insert(IconHandle(i), iconName);
1721     if (isIconFormat44(i)) {
1722         if (i->attributeTheme().isEmpty()) {
1723             // No theme: Write resource icon as is
1724             m_output << m_indent << "QIcon " << iconName << ";\n";
1725             writeResourceIcon(m_output, iconName, m_indent, i);
1726         } else {
1727             // Theme: Generate code to check the theme and default to resource
1728             const QString themeIconName = fixString(i->attributeTheme(), QString());
1729             if (iconHasStatePixmaps(i)) {
1730                 // Theme + default state pixmaps:
1731                 // Generate code to check the theme and default to state pixmaps
1732                 m_output << m_indent << "QIcon " << iconName << ";\n";
1733                 const char themeNameStringVariableC[] = "iconThemeName";
1734                 // Store theme name in a variable
1735                 m_output << m_indent;
1736                 if (m_firstThemeIcon) { // Declare variable string
1737                     m_output << "QString ";
1738                     m_firstThemeIcon = false;
1739                 }
1740                 m_output << themeNameStringVariableC << " = QString::fromUtf8("
1741                          << themeIconName << ");\n";
1742                 m_output << m_indent << "if (QIcon::hasThemeIcon("
1743                          << themeNameStringVariableC
1744                          << ")) {\n"
1745                          << m_dindent << iconName << " = QIcon::fromTheme(" << themeNameStringVariableC << ");\n"
1746                          << m_indent << "} else {\n";
1747                 writeResourceIcon(m_output, iconName, m_dindent, i);
1748                 m_output << m_indent << "}\n";
1749             } else {
1750                 // Theme, but no state pixmaps: Construct from theme directly.
1751                 m_output << m_indent << "QIcon " << iconName
1752                          << "(QIcon::fromTheme(QString::fromUtf8("
1753                          << themeIconName << ")));\n";
1754             } // Theme, but not state
1755         }     // >= 4.4
1756     } else {  // pre-4.4 legacy
1757         m_output <<  m_indent << "const QIcon " << iconName << " = " << pixCall(QLatin1String("QIcon"), i->text())<< ";\n";
1758     }
1759     return iconName;
1760 }
1761 
domColor2QString(const DomColor * c)1762 QString WriteInitialization::domColor2QString(const DomColor *c)
1763 {
1764     if (c->hasAttributeAlpha())
1765         return QString::fromLatin1("QColor(%1, %2, %3, %4)")
1766             .arg(c->elementRed())
1767             .arg(c->elementGreen())
1768             .arg(c->elementBlue())
1769             .arg(c->attributeAlpha());
1770     return QString::fromLatin1("QColor(%1, %2, %3)")
1771         .arg(c->elementRed())
1772         .arg(c->elementGreen())
1773         .arg(c->elementBlue());
1774 }
1775 
writeColorGroup(DomColorGroup * colorGroup,const QString & group,const QString & paletteName)1776 void WriteInitialization::writeColorGroup(DomColorGroup *colorGroup, const QString &group, const QString &paletteName)
1777 {
1778     if (!colorGroup)
1779         return;
1780 
1781     // old format
1782     const QList<DomColor*> colors = colorGroup->elementColor();
1783     for (int i=0; i<colors.size(); ++i) {
1784         const DomColor *color = colors.at(i);
1785 
1786         m_output << m_indent << paletteName << ".setColor(" << group
1787             << ", " << "static_cast<QPalette::ColorRole>(" << QString::number(i) << ')'
1788             << ", " << domColor2QString(color)
1789             << ");\n";
1790     }
1791 
1792     // new format
1793     const QList<DomColorRole *> colorRoles = colorGroup->elementColorRole();
1794     QListIterator<DomColorRole *> itRole(colorRoles);
1795     while (itRole.hasNext()) {
1796         const DomColorRole *colorRole = itRole.next();
1797         if (colorRole->hasAttributeRole()) {
1798             const QString brushName = writeBrushInitialization(colorRole->elementBrush());
1799             m_output << m_indent << paletteName << ".setBrush(" << group
1800                 << ", " << "QPalette::" << colorRole->attributeRole()
1801                 << ", " << brushName << ");\n";
1802         }
1803     }
1804 }
1805 
1806 // Write initialization for brush unless it is found in the cache. Returns the name to use
1807 // in an expression.
writeBrushInitialization(const DomBrush * brush)1808 QString WriteInitialization::writeBrushInitialization(const DomBrush *brush)
1809 {
1810     // Simple solid, colored  brushes are cached
1811     const bool solidColoredBrush = !brush->hasAttributeBrushStyle() || brush->attributeBrushStyle() == QLatin1String("SolidPattern");
1812     uint rgb = 0;
1813     if (solidColoredBrush) {
1814         if (const DomColor *color = brush->elementColor()) {
1815             rgb = ((color->elementRed() & 0xFF) << 24) |
1816                   ((color->elementGreen() & 0xFF) << 16) |
1817                   ((color->elementBlue() & 0xFF) << 8) |
1818                   ((color->attributeAlpha() & 0xFF));
1819             const ColorBrushHash::const_iterator cit = m_colorBrushHash.constFind(rgb);
1820             if (cit != m_colorBrushHash.constEnd())
1821                 return cit.value();
1822         }
1823     }
1824     // Create and enter into cache if simple
1825     const QString brushName = m_driver->unique(QLatin1String("brush"));
1826     writeBrush(brush, brushName);
1827     if (solidColoredBrush)
1828         m_colorBrushHash.insert(rgb, brushName);
1829     return brushName;
1830 }
1831 
writeBrush(const DomBrush * brush,const QString & brushName)1832 void WriteInitialization::writeBrush(const DomBrush *brush, const QString &brushName)
1833 {
1834     QString style = QLatin1String("SolidPattern");
1835     if (brush->hasAttributeBrushStyle())
1836         style = brush->attributeBrushStyle();
1837 
1838     if (style == QLatin1String("LinearGradientPattern") ||
1839             style == QLatin1String("RadialGradientPattern") ||
1840             style == QLatin1String("ConicalGradientPattern")) {
1841         const DomGradient *gradient = brush->elementGradient();
1842         const QString gradientType = gradient->attributeType();
1843         const QString gradientName = m_driver->unique(QLatin1String("gradient"));
1844         if (gradientType == QLatin1String("LinearGradient")) {
1845             m_output << m_indent << "QLinearGradient " << gradientName
1846                 << '(' << gradient->attributeStartX()
1847                 << ", " << gradient->attributeStartY()
1848                 << ", " << gradient->attributeEndX()
1849                 << ", " << gradient->attributeEndY() << ");\n";
1850         } else if (gradientType == QLatin1String("RadialGradient")) {
1851             m_output << m_indent << "QRadialGradient " << gradientName
1852                 << '(' << gradient->attributeCentralX()
1853                 << ", " << gradient->attributeCentralY()
1854                 << ", " << gradient->attributeRadius()
1855                 << ", " << gradient->attributeFocalX()
1856                 << ", " << gradient->attributeFocalY() << ");\n";
1857         } else if (gradientType == QLatin1String("ConicalGradient")) {
1858             m_output << m_indent << "QConicalGradient " << gradientName
1859                 << '(' << gradient->attributeCentralX()
1860                 << ", " << gradient->attributeCentralY()
1861                 << ", " << gradient->attributeAngle() << ");\n";
1862         }
1863 
1864         m_output << m_indent << gradientName << ".setSpread(QGradient::"
1865             << gradient->attributeSpread() << ");\n";
1866 
1867         if (gradient->hasAttributeCoordinateMode()) {
1868             m_output << m_indent << gradientName << ".setCoordinateMode(QGradient::"
1869                 << gradient->attributeCoordinateMode() << ");\n";
1870         }
1871 
1872        const  QList<DomGradientStop *> stops = gradient->elementGradientStop();
1873         QListIterator<DomGradientStop *> it(stops);
1874         while (it.hasNext()) {
1875             const DomGradientStop *stop = it.next();
1876             const DomColor *color = stop->elementColor();
1877             m_output << m_indent << gradientName << ".setColorAt("
1878                 << stop->attributePosition() << ", "
1879                 << domColor2QString(color) << ");\n";
1880         }
1881         m_output << m_indent << "QBrush " << brushName << '('
1882             << gradientName << ");\n";
1883     } else if (style == QLatin1String("TexturePattern")) {
1884         const DomProperty *property = brush->elementTexture();
1885         const QString iconValue = iconCall(property);
1886 
1887         m_output << m_indent << "QBrush " << brushName << " = QBrush("
1888             << iconValue << ");\n";
1889     } else {
1890         const DomColor *color = brush->elementColor();
1891         m_output << m_indent << "QBrush " << brushName << '('
1892             << domColor2QString(color) << ");\n";
1893 
1894         m_output << m_indent << brushName << ".setStyle("
1895             << "Qt::" << style << ");\n";
1896     }
1897 }
1898 
acceptCustomWidget(DomCustomWidget * node)1899 void WriteInitialization::acceptCustomWidget(DomCustomWidget *node)
1900 {
1901     Q_UNUSED(node);
1902 }
1903 
acceptCustomWidgets(DomCustomWidgets * node)1904 void WriteInitialization::acceptCustomWidgets(DomCustomWidgets *node)
1905 {
1906     Q_UNUSED(node);
1907 }
1908 
acceptTabStops(DomTabStops * tabStops)1909 void WriteInitialization::acceptTabStops(DomTabStops *tabStops)
1910 {
1911     QString lastName;
1912 
1913     const QStringList l = tabStops->elementTabStop();
1914     for (int i=0; i<l.size(); ++i) {
1915         const QString name = l.at(i);
1916 
1917         if (!m_registeredWidgets.contains(name)) {
1918             fprintf(stderr, "%s: Warning: Tab-stop assignment: '%s' is not a valid widget.\n",
1919                     qPrintable(m_option.messagePrefix()),
1920                     name.toLatin1().data());
1921             continue;
1922         }
1923 
1924         if (i == 0) {
1925             lastName = name;
1926             continue;
1927         } else if (name.isEmpty() || lastName.isEmpty()) {
1928             continue;
1929         }
1930 
1931         m_output << m_indent << "QWidget::setTabOrder(" << lastName << ", " << name << ");\n";
1932 
1933         lastName = name;
1934     }
1935 }
1936 
initializeQ3ListBox(DomWidget * w)1937 void WriteInitialization::initializeQ3ListBox(DomWidget *w)
1938 {
1939     const QString varName = m_driver->findOrInsertWidget(w);
1940     const QString className = w->attributeClass();
1941 
1942     const QList<DomItem*> items = w->elementItem();
1943 
1944     if (items.isEmpty())
1945         return;
1946 
1947     m_refreshOut << m_indent << varName << "->clear();\n";
1948 
1949     for (int i=0; i<items.size(); ++i) {
1950         const DomItem *item = items.at(i);
1951 
1952         const DomPropertyMap properties = propertyMap(item->elementProperty());
1953         const DomProperty *text = properties.value(QLatin1String("text"));
1954         const DomProperty *pixmap = properties.value(QLatin1String("pixmap"));
1955         if (!(text || pixmap))
1956             continue;
1957 
1958         m_refreshOut << m_indent << varName << "->insertItem(";
1959         if (pixmap) {
1960             m_refreshOut << pixCall(pixmap);
1961 
1962             if (text)
1963                 m_refreshOut << ", ";
1964         }
1965         if (text)
1966             m_refreshOut << trCall(text->elementString());
1967         m_refreshOut << ");\n";
1968     }
1969 }
1970 
initializeQ3IconView(DomWidget * w)1971 void WriteInitialization::initializeQ3IconView(DomWidget *w)
1972 {
1973     const QString varName = m_driver->findOrInsertWidget(w);
1974     const QString className = w->attributeClass();
1975 
1976     const QList<DomItem*> items = w->elementItem();
1977 
1978     if (items.isEmpty())
1979         return;
1980 
1981     m_refreshOut << m_indent << varName << "->clear();\n";
1982 
1983     for (int i=0; i<items.size(); ++i) {
1984         const DomItem *item = items.at(i);
1985 
1986         const DomPropertyMap properties = propertyMap(item->elementProperty());
1987         const DomProperty *text = properties.value(QLatin1String("text"));
1988         const DomProperty *pixmap = properties.value(QLatin1String("pixmap"));
1989         if (!(text || pixmap))
1990             continue;
1991 
1992         const QString itemName = m_driver->unique(QLatin1String("__item"));
1993         m_refreshOut << "\n";
1994         m_refreshOut << m_indent << "Q3IconViewItem *" << itemName << " = new Q3IconViewItem(" << varName << ");\n";
1995 
1996         if (pixmap) {
1997             m_refreshOut << m_indent << itemName << "->setPixmap(" << pixCall(pixmap) << ");\n";
1998         }
1999 
2000         if (text) {
2001             m_refreshOut << m_indent << itemName << "->setText(" << trCall(text->elementString()) << ");\n";
2002         }
2003     }
2004 }
2005 
initializeQ3ListView(DomWidget * w)2006 void WriteInitialization::initializeQ3ListView(DomWidget *w)
2007 {
2008     const QString varName = m_driver->findOrInsertWidget(w);
2009     const QString className = w->attributeClass();
2010 
2011     // columns
2012     const QList<DomColumn*> columns = w->elementColumn();
2013     for (int i=0; i<columns.size(); ++i) {
2014         const DomColumn *column = columns.at(i);
2015 
2016         const DomPropertyMap properties = propertyMap(column->elementProperty());
2017         const DomProperty *text = properties.value(QLatin1String("text"));
2018         const DomProperty *pixmap = properties.value(QLatin1String("pixmap"));
2019         const DomProperty *clickable = properties.value(QLatin1String("clickable"));
2020         const DomProperty *resizable = properties.value(QLatin1String("resizable"));
2021 
2022         const QString txt = trCall(text->elementString());
2023         m_output << m_indent << varName << "->addColumn(" << txt << ");\n";
2024         m_refreshOut << m_indent << varName << "->header()->setLabel(" << i << ", " << txt << ");\n";
2025 
2026         if (pixmap) {
2027             m_output << m_indent << varName << "->header()->setLabel("
2028                    << varName << "->header()->count() - 1, " << pixCall(pixmap) << ", " << txt << ");\n";
2029         }
2030 
2031         if (clickable != 0) {
2032             m_output << m_indent << varName << "->header()->setClickEnabled(" << clickable->elementBool() << ", " << varName << "->header()->count() - 1);\n";
2033         }
2034 
2035         if (resizable != 0) {
2036             m_output << m_indent << varName << "->header()->setResizeEnabled(" << resizable->elementBool() << ", " << varName << "->header()->count() - 1);\n";
2037         }
2038     }
2039 
2040     if (w->elementItem().size()) {
2041         m_refreshOut << m_indent << varName << "->clear();\n";
2042 
2043         initializeQ3ListViewItems(className, varName, w->elementItem());
2044     }
2045 }
2046 
initializeQ3ListViewItems(const QString & className,const QString & varName,const QList<DomItem * > & items)2047 void WriteInitialization::initializeQ3ListViewItems(const QString &className, const QString &varName, const QList<DomItem *> &items)
2048 {
2049     if (items.isEmpty())
2050         return;
2051 
2052     // items
2053     for (int i=0; i<items.size(); ++i) {
2054         const DomItem *item = items.at(i);
2055 
2056         const QString itemName = m_driver->unique(QLatin1String("__item"));
2057         m_refreshOut << "\n";
2058         m_refreshOut << m_indent << "Q3ListViewItem *" << itemName << " = new Q3ListViewItem(" << varName << ");\n";
2059 
2060         int textCount = 0, pixCount = 0;
2061         const DomPropertyList properties = item->elementProperty();
2062         for (int i=0; i<properties.size(); ++i) {
2063             const DomProperty *p = properties.at(i);
2064             if (p->attributeName() == QLatin1String("text"))
2065                 m_refreshOut << m_indent << itemName << "->setText(" << textCount++ << ", "
2066                            << trCall(p->elementString()) << ");\n";
2067 
2068             if (p->attributeName() == QLatin1String("pixmap"))
2069                 m_refreshOut << m_indent << itemName << "->setPixmap(" << pixCount++ << ", "
2070                            << pixCall(p) << ");\n";
2071         }
2072 
2073         if (item->elementItem().size()) {
2074             m_refreshOut << m_indent << itemName << "->setOpen(true);\n";
2075             initializeQ3ListViewItems(className, itemName, item->elementItem());
2076         }
2077     }
2078 }
2079 
2080 
initializeQ3Table(DomWidget * w)2081 void WriteInitialization::initializeQ3Table(DomWidget *w)
2082 {
2083     const QString varName = m_driver->findOrInsertWidget(w);
2084     const QString className = w->attributeClass();
2085 
2086     // columns
2087     const QList<DomColumn*> columns = w->elementColumn();
2088 
2089     for (int i=0; i<columns.size(); ++i) {
2090         const DomColumn *column = columns.at(i);
2091 
2092         const DomPropertyMap properties = propertyMap(column->elementProperty());
2093         const DomProperty *text = properties.value(QLatin1String("text"));
2094         const DomProperty *pixmap = properties.value(QLatin1String("pixmap"));
2095 
2096         m_refreshOut << m_indent << varName << "->horizontalHeader()->setLabel(" << i << ", ";
2097         if (pixmap) {
2098             m_refreshOut << pixCall(pixmap) << ", ";
2099         }
2100         m_refreshOut << trCall(text->elementString()) << ");\n";
2101     }
2102 
2103     // rows
2104     const QList<DomRow*> rows = w->elementRow();
2105     for (int i=0; i<rows.size(); ++i) {
2106         const DomRow *row = rows.at(i);
2107 
2108         const DomPropertyMap properties = propertyMap(row->elementProperty());
2109         const DomProperty *text = properties.value(QLatin1String("text"));
2110         const DomProperty *pixmap = properties.value(QLatin1String("pixmap"));
2111 
2112         m_refreshOut << m_indent << varName << "->verticalHeader()->setLabel(" << i << ", ";
2113         if (pixmap) {
2114             m_refreshOut << pixCall(pixmap) << ", ";
2115         }
2116         m_refreshOut << trCall(text->elementString()) << ");\n";
2117     }
2118 
2119 
2120     //initializeQ3TableItems(className, varName, w->elementItem());
2121 }
2122 
initializeQ3TableItems(const QString & className,const QString & varName,const QList<DomItem * > & items)2123 void WriteInitialization::initializeQ3TableItems(const QString &className, const QString &varName, const QList<DomItem *> &items)
2124 {
2125     Q_UNUSED(className);
2126     Q_UNUSED(varName);
2127     Q_UNUSED(items);
2128 }
2129 
iconCall(const DomProperty * icon)2130 QString WriteInitialization::iconCall(const DomProperty *icon)
2131 {
2132     if (icon->kind() == DomProperty::IconSet)
2133         return writeIconProperties(icon->elementIconSet());
2134     return pixCall(icon);
2135 }
2136 
pixCall(const DomProperty * p) const2137 QString WriteInitialization::pixCall(const DomProperty *p) const
2138 {
2139     QString type, s;
2140     switch (p->kind()) {
2141     case DomProperty::IconSet:
2142         type = QLatin1String("QIcon");
2143         s = p->elementIconSet()->text();
2144         break;
2145     case DomProperty::Pixmap:
2146         type = QLatin1String("QPixmap");
2147         s = p->elementPixmap()->text();
2148         break;
2149     default:
2150         qWarning("%s: Warning: Unknown icon format encountered. The ui-file was generated with a too-recent version of Designer.",
2151                  qPrintable(m_option.messagePrefix()));
2152         return QLatin1String("QIcon()");
2153         break;
2154     }
2155     return pixCall(type, s);
2156 }
2157 
pixCall(const QString & t,const QString & text) const2158 QString WriteInitialization::pixCall(const QString &t, const QString &text) const
2159 {
2160     QString type = t;
2161     if (text.isEmpty()) {
2162         type += QLatin1String("()");
2163         return type;
2164     }
2165     if (const DomImage *image = findImage(text)) {
2166         if (m_option.extractImages) {
2167             const QString format = image->elementData()->attributeFormat();
2168             const QString extension = format.left(format.indexOf(QLatin1Char('.'))).toLower();
2169             QString rc = QLatin1String("QPixmap(QString::fromUtf8(\":/");
2170             rc += m_generatedClass;
2171             rc += QLatin1String("/images/");
2172             rc += text;
2173             rc += QLatin1Char('.');
2174             rc += extension;
2175             rc += QLatin1String("\"))");
2176             return rc;
2177         }
2178         QString rc = WriteIconInitialization::iconFromDataFunction();
2179         rc += QLatin1Char('(');
2180         rc += text;
2181         rc += QLatin1String("_ID)");
2182         return rc;
2183     }
2184 
2185     QString pixFunc = m_uic->pixmapFunction();
2186     if (pixFunc.isEmpty())
2187         pixFunc = QLatin1String("QString::fromUtf8");
2188 
2189     type += QLatin1Char('(');
2190     type += pixFunc;
2191     type += QLatin1Char('(');
2192     type += fixString(text, m_dindent);
2193     type += QLatin1String("))");
2194     return type;
2195 }
2196 
initializeComboBox3(DomWidget * w)2197 void WriteInitialization::initializeComboBox3(DomWidget *w)
2198 {
2199     const QList<DomItem*> items = w->elementItem();
2200     if (items.empty())
2201         return;
2202     // Basic legacy Qt3 support, write out translatable text items, ignore pixmaps
2203     const QString varName = m_driver->findOrInsertWidget(w);
2204     const QString textProperty = QLatin1String("text");
2205 
2206     m_refreshOut << m_indent << varName << "->clear();\n";
2207     m_refreshOut << m_indent << varName << "->insertStringList(QStringList()" << '\n';
2208     const int itemCount = items.size();
2209     for (int i = 0; i< itemCount; ++i) {
2210         const DomItem *item = items.at(i);
2211         if (const DomProperty *text = propertyMap(item->elementProperty()).value(textProperty))
2212             m_refreshOut << m_indent << " << " << autoTrCall(text->elementString()) << "\n";
2213     }
2214     m_refreshOut << m_indent << ", 0);\n";
2215 }
2216 
initializeComboBox(DomWidget * w)2217 void WriteInitialization::initializeComboBox(DomWidget *w)
2218 {
2219     const QString varName = m_driver->findOrInsertWidget(w);
2220     const QString className = w->attributeClass();
2221 
2222     const QList<DomItem*> items = w->elementItem();
2223 
2224     if (items.isEmpty())
2225         return;
2226 
2227     // If possible use qcombobox's addItems() which is much faster then a bunch of addItem() calls
2228     bool makeStringListCall = true;
2229     bool translatable = false;
2230     QStringList list;
2231     for (int i=0; i<items.size(); ++i) {
2232         const DomItem *item = items.at(i);
2233         const DomPropertyMap properties = propertyMap(item->elementProperty());
2234         const DomProperty *text = properties.value(QLatin1String("text"));
2235         const DomProperty *pixmap = properties.value(QLatin1String("icon"));
2236         bool needsTr = needsTranslation(text->elementString());
2237         if (pixmap != 0 || (i > 0 && translatable != needsTr)) {
2238             makeStringListCall = false;
2239             break;
2240         }
2241         translatable = needsTr;
2242         list.append(autoTrCall(text->elementString()));  // fix me here
2243     }
2244 
2245     if (makeStringListCall) {
2246         QTextStream &o = translatable ? m_refreshOut : m_output;
2247         if (translatable)
2248             o << m_indent << varName << "->clear();\n";
2249         o << m_indent << varName << "->insertItems(0, QStringList()" << '\n';
2250         for (int i = 0; i < list.size(); ++i)
2251             o << m_indent << " << " << list.at(i) << "\n";
2252         o << m_indent << ");\n";
2253     } else {
2254         for (int i = 0; i < items.size(); ++i) {
2255             const DomItem *item = items.at(i);
2256             const DomPropertyMap properties = propertyMap(item->elementProperty());
2257             const DomProperty *text = properties.value(QLatin1String("text"));
2258             const DomProperty *icon = properties.value(QLatin1String("icon"));
2259 
2260             QString iconValue;
2261             if (icon)
2262                 iconValue = iconCall(icon);
2263 
2264             m_output << m_indent << varName << "->addItem(";
2265             if (icon)
2266                 m_output << iconValue << ", ";
2267 
2268             if (needsTranslation(text->elementString())) {
2269                 m_output << "QString());\n";
2270                 m_refreshOut << m_indent << varName << "->setItemText(" << i << ", " << trCall(text->elementString()) << ");\n";
2271             } else {
2272                 m_output << noTrCall(text->elementString()) << ");\n";
2273             }
2274         }
2275         m_refreshOut << "\n";
2276     }
2277 }
2278 
disableSorting(DomWidget * w,const QString & varName)2279 QString WriteInitialization::disableSorting(DomWidget *w, const QString &varName)
2280 {
2281     // turn off sortingEnabled to force programmatic item order (setItem())
2282     QString tempName;
2283     if (!w->elementItem().isEmpty()) {
2284         tempName = m_driver->unique(QLatin1String("__sortingEnabled"));
2285         m_refreshOut << "\n";
2286         m_refreshOut << m_indent << "const bool " << tempName
2287             << " = " << varName << "->isSortingEnabled();\n";
2288         m_refreshOut << m_indent << varName << "->setSortingEnabled(false);\n";
2289     }
2290     return tempName;
2291 }
2292 
enableSorting(DomWidget * w,const QString & varName,const QString & tempName)2293 void WriteInitialization::enableSorting(DomWidget *w, const QString &varName, const QString &tempName)
2294 {
2295     if (!w->elementItem().isEmpty()) {
2296         m_refreshOut << m_indent << varName << "->setSortingEnabled(" << tempName << ");\n\n";
2297     }
2298 }
2299 
2300 /*
2301  * Initializers are just strings containing the function call and need to be prepended
2302  * the line indentation and the object they are supposed to initialize.
2303  * String initializers come with a preprocessor conditional (ifdef), so the code
2304  * compiles with QT_NO_xxx. A null pointer means no conditional. String initializers
2305  * are written to the retranslateUi() function, others to setupUi().
2306  */
2307 
2308 
2309 /*!
2310     Create non-string inititializer.
2311     \param value the value to initialize the attribute with. May be empty, in which case
2312         the initializer is omitted.
2313     See above for other parameters.
2314 */
addInitializer(Item * item,const QString & name,int column,const QString & value,const QString & directive,bool translatable) const2315 void WriteInitialization::addInitializer(Item *item,
2316         const QString &name, int column, const QString &value, const QString &directive, bool translatable) const
2317 {
2318     if (!value.isEmpty())
2319         item->addSetter(QLatin1String("->set") + name.at(0).toUpper() + name.mid(1) +
2320                     QLatin1Char('(') + (column < 0 ? QString() : QString::number(column) +
2321                     QLatin1String(", ")) + value + QLatin1String(");"), directive, translatable);
2322 }
2323 
2324 /*!
2325     Create string inititializer.
2326     \param initializers in/out list of inializers
2327     \param properties map property name -> property to extract data from
2328     \param name the property to extract
2329     \param col the item column to generate the initializer for. This is relevant for
2330         tree widgets only. If it is -1, no column index will be generated.
2331     \param ifdef preprocessor symbol for disabling compilation of this initializer
2332 */
addStringInitializer(Item * item,const DomPropertyMap & properties,const QString & name,int column,const QString & directive) const2333 void WriteInitialization::addStringInitializer(Item *item,
2334         const DomPropertyMap &properties, const QString &name, int column, const QString &directive) const
2335 {
2336     if (const DomProperty *p = properties.value(name)) {
2337         DomString *str = p->elementString();
2338         QString text = toString(str);
2339         if (!text.isEmpty()) {
2340             bool translatable = needsTranslation(str);
2341             QString value = autoTrCall(str);
2342             addInitializer(item, name, column, value, directive, translatable);
2343         }
2344     }
2345 }
2346 
addBrushInitializer(Item * item,const DomPropertyMap & properties,const QString & name,int column)2347 void WriteInitialization::addBrushInitializer(Item *item,
2348         const DomPropertyMap &properties, const QString &name, int column)
2349 {
2350     if (const DomProperty *p = properties.value(name)) {
2351         if (p->elementBrush())
2352             addInitializer(item, name, column, writeBrushInitialization(p->elementBrush()));
2353         else if (p->elementColor())
2354             addInitializer(item, name, column, domColor2QString(p->elementColor()));
2355     }
2356 }
2357 
2358 /*!
2359     Create inititializer for a flag value in the Qt namespace.
2360     If the named property is not in the map, the initializer is omitted.
2361 */
addQtFlagsInitializer(Item * item,const DomPropertyMap & properties,const QString & name,int column) const2362 void WriteInitialization::addQtFlagsInitializer(Item *item,
2363         const DomPropertyMap &properties, const QString &name, int column) const
2364 {
2365     if (const DomProperty *p = properties.value(name)) {
2366         QString v = p->elementSet();
2367         if (!v.isEmpty()) {
2368             v.replace(QLatin1Char('|'), QLatin1String("|Qt::"));
2369             addInitializer(item, name, column, QLatin1String("Qt::") + v);
2370         }
2371     }
2372 }
2373 
2374 /*!
2375     Create inititializer for an enum value in the Qt namespace.
2376     If the named property is not in the map, the initializer is omitted.
2377 */
addQtEnumInitializer(Item * item,const DomPropertyMap & properties,const QString & name,int column) const2378 void WriteInitialization::addQtEnumInitializer(Item *item,
2379         const DomPropertyMap &properties, const QString &name, int column) const
2380 {
2381     if (const DomProperty *p = properties.value(name)) {
2382         QString v = p->elementEnum();
2383         if (!v.isEmpty())
2384             addInitializer(item, name, column, QLatin1String("Qt::") + v);
2385     }
2386 }
2387 
2388 /*!
2389     Create inititializers for all common properties that may be bound to a column.
2390 */
addCommonInitializers(Item * item,const DomPropertyMap & properties,int column)2391 void WriteInitialization::addCommonInitializers(Item *item,
2392         const DomPropertyMap &properties, int column)
2393 {
2394     if (const DomProperty *icon = properties.value(QLatin1String("icon")))
2395         addInitializer(item, QLatin1String("icon"), column, iconCall(icon));
2396     addBrushInitializer(item, properties, QLatin1String("foreground"), column);
2397     addBrushInitializer(item, properties, QLatin1String("background"), column);
2398     if (const DomProperty *font = properties.value(QLatin1String("font")))
2399         addInitializer(item, QLatin1String("font"), column, writeFontProperties(font->elementFont()));
2400     addQtFlagsInitializer(item, properties, QLatin1String("textAlignment"), column);
2401     addQtEnumInitializer(item, properties, QLatin1String("checkState"), column);
2402     addStringInitializer(item, properties, QLatin1String("text"), column);
2403     addStringInitializer(item, properties, QLatin1String("toolTip"), column, QLatin1String(toolTipDefineC));
2404     addStringInitializer(item, properties, QLatin1String("whatsThis"), column, QLatin1String(whatsThisDefineC));
2405     addStringInitializer(item, properties, QLatin1String("statusTip"), column, QLatin1String(statusTipDefineC));
2406 }
2407 
initializeListWidget(DomWidget * w)2408 void WriteInitialization::initializeListWidget(DomWidget *w)
2409 {
2410     const QString varName = m_driver->findOrInsertWidget(w);
2411     const QString className = w->attributeClass();
2412 
2413     const QList<DomItem*> items = w->elementItem();
2414 
2415     if (items.isEmpty())
2416         return;
2417 
2418     QString tempName = disableSorting(w, varName);
2419     // items
2420     // TODO: the generated code should be data-driven to reduce its size
2421     for (int i = 0; i < items.size(); ++i) {
2422         const DomItem *domItem = items.at(i);
2423 
2424         const DomPropertyMap properties = propertyMap(domItem->elementProperty());
2425 
2426         Item item(QLatin1String("QListWidgetItem"), m_indent, m_output, m_refreshOut, m_driver);
2427         addQtFlagsInitializer(&item, properties, QLatin1String("flags"));
2428         addCommonInitializers(&item, properties);
2429 
2430         item.writeSetupUi(varName);
2431         item.writeRetranslateUi(varName + QLatin1String("->item(") + QString::number(i) + QLatin1Char(')'));
2432     }
2433     enableSorting(w, varName, tempName);
2434 }
2435 
initializeTreeWidget(DomWidget * w)2436 void WriteInitialization::initializeTreeWidget(DomWidget *w)
2437 {
2438     const QString varName = m_driver->findOrInsertWidget(w);
2439 
2440     // columns
2441     Item item(QLatin1String("QTreeWidgetItem"), m_indent, m_output, m_refreshOut, m_driver);
2442 
2443     const QList<DomColumn*> columns = w->elementColumn();
2444     for (int i = 0; i < columns.size(); ++i) {
2445         const DomColumn *column = columns.at(i);
2446 
2447         const DomPropertyMap properties = propertyMap(column->elementProperty());
2448         addCommonInitializers(&item, properties, i);
2449     }
2450     const QString itemName = item.writeSetupUi(QString(), Item::DontConstruct);
2451     item.writeRetranslateUi(varName + QLatin1String("->headerItem()"));
2452     if (!itemName.isNull())
2453         m_output << m_indent << varName << "->setHeaderItem(" << itemName << ");\n";
2454 
2455     if (w->elementItem().size() == 0)
2456         return;
2457 
2458     QString tempName = disableSorting(w, varName);
2459 
2460     QList<Item *> items = initializeTreeWidgetItems(w->elementItem());
2461     for (int i = 0; i < items.count(); i++) {
2462         Item *itm = items[i];
2463         itm->writeSetupUi(varName);
2464         itm->writeRetranslateUi(varName + QLatin1String("->topLevelItem(") + QString::number(i) + QLatin1Char(')'));
2465         delete itm;
2466     }
2467 
2468     enableSorting(w, varName, tempName);
2469 }
2470 
2471 /*!
2472     Create and write out initializers for tree widget items.
2473     This function makes sure that only needed items are fetched (subject to preprocessor
2474     conditionals), that each item is fetched from its parent widget/item exactly once
2475     and that no temporary variables are created for items that are needed only once. As
2476     fetches are built top-down from the root, but determining how often and under which
2477     conditions an item is needed needs to be done bottom-up, the whole process makes
2478     two passes, storing the intermediate result in a recursive StringInitializerListMap.
2479 */
initializeTreeWidgetItems(const QList<DomItem * > & domItems)2480 QList<WriteInitialization::Item *> WriteInitialization::initializeTreeWidgetItems(const QList<DomItem *> &domItems)
2481 {
2482     // items
2483     QList<Item *> items;
2484 
2485     for (int i = 0; i < domItems.size(); ++i) {
2486         const DomItem *domItem = domItems.at(i);
2487 
2488         Item *item = new Item(QLatin1String("QTreeWidgetItem"), m_indent, m_output, m_refreshOut, m_driver);
2489         items << item;
2490 
2491         QHash<QString, DomProperty *> map;
2492 
2493         int col = -1;
2494         const DomPropertyList properties = domItem->elementProperty();
2495         for (int j = 0; j < properties.size(); ++j) {
2496             DomProperty *p = properties.at(j);
2497             if (p->attributeName() == QLatin1String("text")) {
2498                 if (!map.isEmpty()) {
2499                     addCommonInitializers(item, map, col);
2500                     map.clear();
2501                 }
2502                 col++;
2503             }
2504             map.insert(p->attributeName(), p);
2505         }
2506         addCommonInitializers(item, map, col);
2507         // AbstractFromBuilder saves flags last, so they always end up in the last column's map.
2508         addQtFlagsInitializer(item, map, QLatin1String("flags"));
2509 
2510         QList<Item *> subItems = initializeTreeWidgetItems(domItem->elementItem());
2511         foreach (Item *subItem, subItems)
2512             item->addChild(subItem);
2513     }
2514     return items;
2515 }
2516 
initializeTableWidget(DomWidget * w)2517 void WriteInitialization::initializeTableWidget(DomWidget *w)
2518 {
2519     const QString varName = m_driver->findOrInsertWidget(w);
2520 
2521     // columns
2522     const QList<DomColumn *> columns = w->elementColumn();
2523 
2524     if (columns.size() != 0) {
2525         m_output << m_indent << "if (" << varName << "->columnCount() < " << columns.size() << ")\n"
2526             << m_dindent << varName << "->setColumnCount(" << columns.size() << ");\n";
2527     }
2528 
2529     for (int i = 0; i < columns.size(); ++i) {
2530         const DomColumn *column = columns.at(i);
2531         if (!column->elementProperty().isEmpty()) {
2532             const DomPropertyMap properties = propertyMap(column->elementProperty());
2533 
2534             Item item(QLatin1String("QTableWidgetItem"), m_indent, m_output, m_refreshOut, m_driver);
2535             addCommonInitializers(&item, properties);
2536 
2537             QString itemName = item.writeSetupUi(QString(), Item::ConstructItemAndVariable);
2538             item.writeRetranslateUi(varName + QLatin1String("->horizontalHeaderItem(") + QString::number(i) + QLatin1Char(')'));
2539             m_output << m_indent << varName << "->setHorizontalHeaderItem(" << QString::number(i) << ", " << itemName << ");\n";
2540         }
2541     }
2542 
2543     // rows
2544     const QList<DomRow *> rows = w->elementRow();
2545 
2546     if (rows.size() != 0) {
2547         m_output << m_indent << "if (" << varName << "->rowCount() < " << rows.size() << ")\n"
2548             << m_dindent << varName << "->setRowCount(" << rows.size() << ");\n";
2549     }
2550 
2551     for (int i = 0; i < rows.size(); ++i) {
2552         const DomRow *row = rows.at(i);
2553         if (!row->elementProperty().isEmpty()) {
2554             const DomPropertyMap properties = propertyMap(row->elementProperty());
2555 
2556             Item item(QLatin1String("QTableWidgetItem"), m_indent, m_output, m_refreshOut, m_driver);
2557             addCommonInitializers(&item, properties);
2558 
2559             QString itemName = item.writeSetupUi(QString(), Item::ConstructItemAndVariable);
2560             item.writeRetranslateUi(varName + QLatin1String("->verticalHeaderItem(") + QString::number(i) + QLatin1Char(')'));
2561             m_output << m_indent << varName << "->setVerticalHeaderItem(" << QString::number(i) << ", " << itemName << ");\n";
2562         }
2563     }
2564 
2565     // items
2566     QString tempName = disableSorting(w, varName);
2567 
2568     const QList<DomItem *> items = w->elementItem();
2569 
2570     for (int i = 0; i < items.size(); ++i) {
2571         const DomItem *cell = items.at(i);
2572         if (cell->hasAttributeRow() && cell->hasAttributeColumn() && !cell->elementProperty().isEmpty()) {
2573             const int r = cell->attributeRow();
2574             const int c = cell->attributeColumn();
2575             const DomPropertyMap properties = propertyMap(cell->elementProperty());
2576 
2577             Item item(QLatin1String("QTableWidgetItem"), m_indent, m_output, m_refreshOut, m_driver);
2578             addQtFlagsInitializer(&item, properties, QLatin1String("flags"));
2579             addCommonInitializers(&item, properties);
2580 
2581             QString itemName = item.writeSetupUi(QString(), Item::ConstructItemAndVariable);
2582             item.writeRetranslateUi(varName + QLatin1String("->item(") + QString::number(r) + QLatin1String(", ") + QString::number(c) + QLatin1Char(')'));
2583             m_output << m_indent << varName << "->setItem(" << QString::number(r) << ", " << QString::number(c) << ", " << itemName << ");\n";
2584         }
2585     }
2586     enableSorting(w, varName, tempName);
2587 }
2588 
trCall(const QString & str,const QString & commentHint) const2589 QString WriteInitialization::trCall(const QString &str, const QString &commentHint) const
2590 {
2591     if (str.isEmpty())
2592         return QLatin1String("QString()");
2593 
2594     QString result;
2595     const QString comment = commentHint.isEmpty() ? QString(QLatin1Char('0')) : fixString(commentHint, m_dindent);
2596 
2597     if (m_option.translateFunction.isEmpty()) {
2598         result = QLatin1String("QApplication::translate(\"");
2599         result += m_generatedClass;
2600         result += QLatin1Char('"');
2601         result += QLatin1String(", ");
2602     } else {
2603         result = m_option.translateFunction;
2604         result += QLatin1Char('(');
2605     }
2606 
2607     result += fixString(str, m_dindent);
2608     result += QLatin1String(", ");
2609     result += comment;
2610 
2611     if (m_option.translateFunction.isEmpty()) {
2612         result += QLatin1String(", ");
2613         result += QLatin1String("QApplication::UnicodeUTF8");
2614     }
2615 
2616     result += QLatin1Char(')');
2617     return result;
2618 }
2619 
initializeQ3SqlDataTable(DomWidget * w)2620 void WriteInitialization::initializeQ3SqlDataTable(DomWidget *w)
2621 {
2622     const DomPropertyMap properties = propertyMap(w->elementProperty());
2623 
2624     const DomProperty *frameworkCode = properties.value(QLatin1String("frameworkCode"), 0);
2625     if (frameworkCode && toBool(frameworkCode->elementBool()) == false)
2626         return;
2627 
2628     QString connection;
2629     QString table;
2630     QString field;
2631 
2632     const DomProperty *db = properties.value(QLatin1String("database"), 0);
2633     if (db && db->elementStringList()) {
2634         const QStringList info = db->elementStringList()->elementString();
2635         connection = info.size() > 0 ? info.at(0) : QString();
2636         table = info.size() > 1 ? info.at(1) : QString();
2637         field = info.size() > 2 ? info.at(2) : QString();
2638     }
2639 
2640     if (table.isEmpty() || connection.isEmpty()) {
2641         fprintf(stderr, "%s: Warning: Invalid database connection\n", qPrintable(m_option.messagePrefix()));
2642         return;
2643     }
2644 
2645    const QString varName = m_driver->findOrInsertWidget(w);
2646 
2647     m_output << m_indent << "if (!" << varName << "->sqlCursor()) {\n";
2648 
2649     m_output << m_dindent << varName << "->setSqlCursor(";
2650 
2651     if (connection == QLatin1String("(default)")) {
2652         m_output << "new Q3SqlCursor(" << fixString(table, m_dindent) << "), false, true);\n";
2653     } else {
2654         m_output << "new Q3SqlCursor(" << fixString(table, m_dindent) << ", true, " << connection << "Connection" << "), false, true);\n";
2655     }
2656     m_output << m_dindent << varName << "->refresh(Q3DataTable::RefreshAll);\n";
2657     m_output << m_indent << "}\n";
2658 }
2659 
initializeQ3SqlDataBrowser(DomWidget * w)2660 void WriteInitialization::initializeQ3SqlDataBrowser(DomWidget *w)
2661 {
2662     const DomPropertyMap properties = propertyMap(w->elementProperty());
2663 
2664     const DomProperty *frameworkCode = properties.value(QLatin1String("frameworkCode"), 0);
2665     if (frameworkCode && toBool(frameworkCode->elementBool()) == false)
2666         return;
2667 
2668     QString connection;
2669     QString table;
2670     QString field;
2671 
2672     const DomProperty *db = properties.value(QLatin1String("database"), 0);
2673     if (db && db->elementStringList()) {
2674         const QStringList info = db->elementStringList()->elementString();
2675         connection = info.size() > 0 ? info.at(0) : QString();
2676         table = info.size() > 1 ? info.at(1) : QString();
2677         field = info.size() > 2 ? info.at(2) : QString();
2678     }
2679 
2680     if (table.isEmpty() || connection.isEmpty()) {
2681         fprintf(stderr, "%s: Warning: Invalid database connection\n", qPrintable(m_option.messagePrefix()));
2682         return;
2683     }
2684 
2685     const QString varName = m_driver->findOrInsertWidget(w);
2686 
2687     m_output << m_indent << "if (!" << varName << "->sqlCursor()) {\n";
2688 
2689     m_output << m_dindent << varName << "->setSqlCursor(";
2690 
2691     if (connection == QLatin1String("(default)")) {
2692         m_output << "new Q3SqlCursor(" << fixString(table, m_dindent) << "), true);\n";
2693     } else {
2694         m_output << "new Q3SqlCursor(" << fixString(table, m_dindent) << ", true, " << connection << "Connection" << "), false, true);\n";
2695     }
2696     m_output << m_dindent << varName << "->refresh();\n";
2697     m_output << m_indent << "}\n";
2698 }
2699 
initializeMenu(DomWidget * w,const QString &)2700 void WriteInitialization::initializeMenu(DomWidget *w, const QString &/*parentWidget*/)
2701 {
2702     const QString menuName = m_driver->findOrInsertWidget(w);
2703     const QString menuAction = menuName + QLatin1String("Action");
2704 
2705     const DomAction *action = m_driver->actionByName(menuAction);
2706     if (action && action->hasAttributeMenu()) {
2707         m_output << m_indent << menuAction << " = " << menuName << "->menuAction();\n";
2708     }
2709 }
2710 
trCall(DomString * str,const QString & defaultString) const2711 QString WriteInitialization::trCall(DomString *str, const QString &defaultString) const
2712 {
2713     QString value = defaultString;
2714     QString comment;
2715     if (str) {
2716         value = toString(str);
2717         comment = str->attributeComment();
2718     }
2719     return trCall(value, comment);
2720 }
2721 
noTrCall(DomString * str,const QString & defaultString) const2722 QString WriteInitialization::noTrCall(DomString *str, const QString &defaultString) const
2723 {
2724     QString value = defaultString;
2725     if (!str && defaultString.isEmpty())
2726         return QString();
2727     if (str)
2728         value = str->text();
2729     QString ret = QLatin1String("QString::fromUtf8(");
2730     ret += fixString(value, m_dindent);
2731     ret += QLatin1Char(')');
2732     return ret;
2733 }
2734 
autoTrCall(DomString * str,const QString & defaultString) const2735 QString WriteInitialization::autoTrCall(DomString *str, const QString &defaultString) const
2736 {
2737     if ((!str && !defaultString.isEmpty()) || needsTranslation(str))
2738         return trCall(str, defaultString);
2739     return noTrCall(str, defaultString);
2740 }
2741 
autoTrOutput(DomString * str,const QString & defaultString)2742 QTextStream &WriteInitialization::autoTrOutput(DomString *str, const QString &defaultString)
2743 {
2744     if ((!str && !defaultString.isEmpty()) || needsTranslation(str))
2745         return m_refreshOut;
2746     return m_output;
2747 }
2748 
isValidObject(const QString & name) const2749 bool WriteInitialization::isValidObject(const QString &name) const
2750 {
2751     return m_registeredWidgets.contains(name)
2752         || m_registeredActions.contains(name);
2753 }
2754 
findDeclaration(const QString & name)2755 QString WriteInitialization::findDeclaration(const QString &name)
2756 {
2757     const QString normalized = Driver::normalizedName(name);
2758 
2759     if (DomWidget *widget = m_driver->widgetByName(normalized))
2760         return m_driver->findOrInsertWidget(widget);
2761     if (DomAction *action = m_driver->actionByName(normalized))
2762         return m_driver->findOrInsertAction(action);
2763     if (const DomButtonGroup *group = m_driver->findButtonGroup(normalized))
2764         return m_driver->findOrInsertButtonGroup(group);
2765     return QString();
2766 }
2767 
acceptConnection(DomConnection * connection)2768 void WriteInitialization::acceptConnection(DomConnection *connection)
2769 {
2770     const QString sender = findDeclaration(connection->elementSender());
2771     const QString receiver = findDeclaration(connection->elementReceiver());
2772 
2773     if (sender.isEmpty() || receiver.isEmpty())
2774         return;
2775 
2776     m_output << m_indent << "QObject::connect("
2777         << sender
2778         << ", "
2779         << "SIGNAL("<<connection->elementSignal()<<')'
2780         << ", "
2781         << receiver
2782         << ", "
2783         << "SLOT("<<connection->elementSlot()<<')'
2784         << ");\n";
2785 }
2786 
findImage(const QString & name) const2787 DomImage *WriteInitialization::findImage(const QString &name) const
2788 {
2789     return m_registeredImages.value(name);
2790 }
2791 
findWidget(const QLatin1String & widgetClass)2792 DomWidget *WriteInitialization::findWidget(const QLatin1String &widgetClass)
2793 {
2794     for (int i = m_widgetChain.count() - 1; i >= 0; --i) {
2795         DomWidget *widget = m_widgetChain.at(i);
2796 
2797         if (widget && m_uic->customWidgetsInfo()->extends(widget->attributeClass(), widgetClass))
2798             return widget;
2799     }
2800 
2801     return 0;
2802 }
2803 
acceptImage(DomImage * image)2804 void WriteInitialization::acceptImage(DomImage *image)
2805 {
2806     if (!image->hasAttributeName())
2807         return;
2808 
2809     m_registeredImages.insert(image->attributeName(), image);
2810 }
2811 
acceptWidgetScripts(const DomScripts & widgetScripts,DomWidget * node,const DomWidgets & childWidgets)2812 void WriteInitialization::acceptWidgetScripts(const DomScripts &widgetScripts, DomWidget *node, const  DomWidgets &childWidgets)
2813 {
2814     // Add the per-class custom scripts to the per-widget ones.
2815     DomScripts scripts(widgetScripts);
2816 
2817     if (DomScript *customWidgetScript = m_uic->customWidgetsInfo()->customWidgetScript(node->attributeClass()))
2818         scripts.push_front(customWidgetScript);
2819 
2820     if (scripts.empty())
2821         return;
2822 
2823     // concatenate script snippets
2824     QString script;
2825     foreach (const DomScript *domScript, scripts) {
2826         const QString snippet = domScript->text();
2827         if (!snippet.isEmpty()) {
2828             script += snippet.trimmed();
2829             script += QLatin1Char('\n');
2830         }
2831     }
2832     if (script.isEmpty())
2833         return;
2834 
2835     // Build the list of children and insert call
2836     m_output << m_indent << "childWidgets.clear();\n";
2837     if (!childWidgets.empty()) {
2838         m_output << m_indent <<  "childWidgets";
2839         foreach (DomWidget *child, childWidgets) {
2840             m_output << " << " << m_driver->findOrInsertWidget(child);
2841         }
2842         m_output << ";\n";
2843     }
2844     m_output << m_indent << "scriptContext.run(QString::fromUtf8("
2845              << fixString(script, m_dindent) << "), "
2846              << m_driver->findOrInsertWidget(node) << ", childWidgets);\n";
2847 }
2848 
2849 
generateMultiDirectiveBegin(QTextStream & outputStream,const QSet<QString> & directives)2850 static void generateMultiDirectiveBegin(QTextStream &outputStream, const QSet<QString> &directives)
2851 {
2852     if (directives.isEmpty())
2853         return;
2854 
2855     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
2856     foreach (const QString &str, directives)
2857         map.insert(str, true);
2858 
2859     if (map.size() == 1) {
2860         outputStream << "#ifndef " << map.constBegin().key() << endl;
2861         return;
2862     }
2863 
2864     outputStream << "#if";
2865     bool doOr = false;
2866     foreach (const QString &str, map.keys()) {
2867         if (doOr)
2868             outputStream << " ||";
2869         outputStream << " !defined(" << str << ')';
2870         doOr = true;
2871     }
2872     outputStream << endl;
2873 }
2874 
generateMultiDirectiveEnd(QTextStream & outputStream,const QSet<QString> & directives)2875 static void generateMultiDirectiveEnd(QTextStream &outputStream, const QSet<QString> &directives)
2876 {
2877     if (directives.isEmpty())
2878         return;
2879 
2880     outputStream << "#endif" << endl;
2881 }
2882 
Item(const QString & itemClassName,const QString & indent,QTextStream & setupUiStream,QTextStream & retranslateUiStream,Driver * driver)2883 WriteInitialization::Item::Item(const QString &itemClassName, const QString &indent, QTextStream &setupUiStream, QTextStream &retranslateUiStream, Driver *driver)
2884     :
2885     m_parent(0),
2886     m_itemClassName(itemClassName),
2887     m_indent(indent),
2888     m_setupUiStream(setupUiStream),
2889     m_retranslateUiStream(retranslateUiStream),
2890     m_driver(driver)
2891 {
2892 
2893 }
2894 
~Item()2895 WriteInitialization::Item::~Item()
2896 {
2897     foreach (Item *child, m_children)
2898         delete child;
2899 }
2900 
writeSetupUi(const QString & parent,Item::EmptyItemPolicy emptyItemPolicy)2901 QString WriteInitialization::Item::writeSetupUi(const QString &parent, Item::EmptyItemPolicy emptyItemPolicy)
2902 {
2903     if (emptyItemPolicy == Item::DontConstruct && m_setupUiData.policy == ItemData::DontGenerate)
2904         return QString();
2905 
2906     bool generateMultiDirective = false;
2907     if (emptyItemPolicy == Item::ConstructItemOnly && m_children.size() == 0) {
2908         if (m_setupUiData.policy == ItemData::DontGenerate) {
2909             m_setupUiStream << m_indent << "new " << m_itemClassName << '(' << parent << ");\n";
2910                 return QString();
2911         } else if (m_setupUiData.policy == ItemData::GenerateWithMultiDirective) {
2912             generateMultiDirective = true;
2913         }
2914     }
2915 
2916     if (generateMultiDirective)
2917         generateMultiDirectiveBegin(m_setupUiStream, m_setupUiData.directives);
2918 
2919     const QString uniqueName = m_driver->unique(QLatin1String("__") + m_itemClassName.toLower());
2920     m_setupUiStream << m_indent << m_itemClassName << " *" << uniqueName << " = new " << m_itemClassName << '(' << parent << ");\n";
2921 
2922     if (generateMultiDirective) {
2923         m_setupUiStream << "#else\n";
2924         m_setupUiStream << m_indent << "new " << m_itemClassName << '(' << parent << ");\n";
2925         generateMultiDirectiveEnd(m_setupUiStream, m_setupUiData.directives);
2926     }
2927 
2928     QMultiMap<QString, QString>::ConstIterator it = m_setupUiData.setters.constBegin();
2929     while (it != m_setupUiData.setters.constEnd()) {
2930         openIfndef(m_setupUiStream, it.key());
2931         m_setupUiStream << m_indent << uniqueName << it.value() << endl;
2932         closeIfndef(m_setupUiStream, it.key());
2933         ++it;
2934     }
2935     foreach (Item *child, m_children)
2936         child->writeSetupUi(uniqueName);
2937     return uniqueName;
2938 }
2939 
writeRetranslateUi(const QString & parentPath)2940 void WriteInitialization::Item::writeRetranslateUi(const QString &parentPath)
2941 {
2942     if (m_retranslateUiData.policy == ItemData::DontGenerate)
2943         return;
2944 
2945     if (m_retranslateUiData.policy == ItemData::GenerateWithMultiDirective)
2946         generateMultiDirectiveBegin(m_retranslateUiStream, m_retranslateUiData.directives);
2947 
2948     const QString uniqueName = m_driver->unique(QLatin1String("___") + m_itemClassName.toLower());
2949     m_retranslateUiStream << m_indent << m_itemClassName << " *" << uniqueName << " = " << parentPath << ";\n";
2950 
2951     if (m_retranslateUiData.policy == ItemData::GenerateWithMultiDirective)
2952         generateMultiDirectiveEnd(m_retranslateUiStream, m_retranslateUiData.directives);
2953 
2954     QString oldDirective;
2955     QMultiMap<QString, QString>::ConstIterator it = m_retranslateUiData.setters.constBegin();
2956     while (it != m_retranslateUiData.setters.constEnd()) {
2957         const QString newDirective = it.key();
2958         if (oldDirective != newDirective) {
2959             closeIfndef(m_retranslateUiStream, oldDirective);
2960             openIfndef(m_retranslateUiStream, newDirective);
2961             oldDirective = newDirective;
2962         }
2963         m_retranslateUiStream << m_indent << uniqueName << it.value() << endl;
2964         ++it;
2965     }
2966     closeIfndef(m_retranslateUiStream, oldDirective);
2967 
2968     for (int i = 0; i < m_children.size(); i++)
2969         m_children[i]->writeRetranslateUi(uniqueName + QLatin1String("->child(") + QString::number(i) + QLatin1Char(')'));
2970 }
2971 
addSetter(const QString & setter,const QString & directive,bool translatable)2972 void WriteInitialization::Item::addSetter(const QString &setter, const QString &directive, bool translatable)
2973 {
2974     const ItemData::TemporaryVariableGeneratorPolicy newPolicy = directive.isNull() ? ItemData::Generate : ItemData::GenerateWithMultiDirective;
2975     if (translatable) {
2976         m_retranslateUiData.setters.insert(directive, setter);
2977         if (ItemData::GenerateWithMultiDirective == newPolicy)
2978             m_retranslateUiData.directives << directive;
2979         if (m_retranslateUiData.policy < newPolicy)
2980             m_retranslateUiData.policy = newPolicy;
2981     } else {
2982         m_setupUiData.setters.insert(directive, setter);
2983         if (ItemData::GenerateWithMultiDirective == newPolicy)
2984             m_setupUiData.directives << directive;
2985         if (m_setupUiData.policy < newPolicy)
2986             m_setupUiData.policy = newPolicy;
2987     }
2988 }
2989 
addChild(Item * child)2990 void WriteInitialization::Item::addChild(Item *child)
2991 {
2992     m_children << child;
2993     child->m_parent = this;
2994 
2995     Item *c = child;
2996     Item *p = this;
2997     while (p) {
2998         p->m_setupUiData.directives |= c->m_setupUiData.directives;
2999         p->m_retranslateUiData.directives |= c->m_retranslateUiData.directives;
3000         if (p->m_setupUiData.policy < c->m_setupUiData.policy)
3001             p->m_setupUiData.policy = c->m_setupUiData.policy;
3002         if (p->m_retranslateUiData.policy < c->m_retranslateUiData.policy)
3003             p->m_retranslateUiData.policy = c->m_retranslateUiData.policy;
3004         c = p;
3005         p = p->m_parent;
3006     }
3007 }
3008 
3009 
3010 } // namespace CPP
3011 
3012 QT_END_NAMESPACE
3013