/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "cppwriteinitialization.h" #include "driver.h" #include "ui4.h" #include "utils.h" #include "uic.h" #include "databaseinfo.h" #include "globaldefs.h" #include #include #include #include QT_BEGIN_NAMESPACE namespace { // Fixup an enumeration name from class Qt. // They are currently stored as "BottomToolBarArea" instead of "Qt::BottomToolBarArea". // due to MO issues. This might be fixed in the future. QLatin1String qtEnumerationPrefix(const QString &name) { static const QLatin1String prefix("Qt::"); if (name.indexOf(prefix) != 0) return prefix; return QLatin1String(); } // figure out the toolbar area of a DOM attrib list. // By legacy, it is stored as an integer. As of 4.3.0, it is the enumeration value. QString toolBarAreaStringFromDOMAttributes(const CPP::WriteInitialization::DomPropertyMap &attributes) { const DomProperty *pstyle = attributes.value(QLatin1String("toolBarArea")); if (!pstyle) return QString(); switch (pstyle->kind()) { case DomProperty::Number: { return QLatin1String("static_cast(") + QString::number(pstyle->elementNumber()) + QLatin1String("), "); } case DomProperty::Enum: { const QString area = pstyle->elementEnum(); return qtEnumerationPrefix(area) + area + QLatin1String(", "); } default: break; } return QString(); } // Write a statement to create a spacer item. void writeSpacerItem(const DomSpacer *node, QTextStream &output) { const QHash properties = propertyMap(node->elementProperty()); output << "new QSpacerItem("; int w = 0; int h = 0; if (const DomProperty *sh = properties.value(QLatin1String("sizeHint"))) { if (const DomSize *sizeHint = sh->elementSize()) { w = sizeHint->elementWidth(); h = sizeHint->elementHeight(); } } output << w << ", " << h << ", "; // size type QString sizeType; if (const DomProperty *st = properties.value(QLatin1String("sizeType"))) { const QString value = st->elementEnum(); if (value.startsWith(QLatin1String("QSizePolicy::"))) sizeType = value; else sizeType = QLatin1String("QSizePolicy::") + value; } else { sizeType = QStringLiteral("QSizePolicy::Expanding"); } // orientation bool isVspacer = false; if (const DomProperty *o = properties.value(QLatin1String("orientation"))) { const QString orientation = o->elementEnum(); if (orientation == QLatin1String("Qt::Vertical") || orientation == QLatin1String("Vertical")) isVspacer = true; } if (isVspacer) output << "QSizePolicy::Minimum, " << sizeType << ')'; else output << sizeType << ", QSizePolicy::Minimum)"; } // Helper for implementing comparison functions for integers. int compareInt(int i1, int i2) { if (i1 < i2) return -1; if (i1 > i2) return 1; return 0; } // Write object->setFoo(x); template void writeSetter(const QString &indent, const QString &varName,const QString &setter, Value v, QTextStream &str) { str << indent << varName << "->" << setter << '(' << v << ");\n"; } static inline bool iconHasStatePixmaps(const DomResourceIcon *i) { return i->hasElementNormalOff() || i->hasElementNormalOn() || i->hasElementDisabledOff() || i->hasElementDisabledOn() || i->hasElementActiveOff() || i->hasElementActiveOn() || i->hasElementSelectedOff() || i->hasElementSelectedOn(); } static inline bool isIconFormat44(const DomResourceIcon *i) { return iconHasStatePixmaps(i) || !i->attributeTheme().isEmpty(); } // Check on properties. Filter out empty legacy pixmap/icon properties // as Designer pre 4.4 used to remove missing resource references. // This can no longer be handled by the code as we have 'setIcon(QIcon())' as well as 'QIcon icon' static bool checkProperty(const QString &fileName, const DomProperty *p) { switch (p->kind()) { case DomProperty::IconSet: if (const DomResourceIcon *dri = p->elementIconSet()) { if (!isIconFormat44(dri)) { if (dri->text().isEmpty()) { const QString msg = QString::fromLatin1("%1: Warning: An invalid icon property '%2' was encountered.") .arg(fileName, p->attributeName()); qWarning("%s", qPrintable(msg)); return false; } } } break; case DomProperty::Pixmap: if (const DomResourcePixmap *drp = p->elementPixmap()) if (drp->text().isEmpty()) { const QString msg = QString::fromUtf8("%1: Warning: An invalid pixmap property '%2' was encountered.") .arg(fileName, p->attributeName()); qWarning("%s", qPrintable(msg)); return false; } break; default: break; } return true; } inline void openIfndef(QTextStream &str, const QString &symbol) { if (!symbol.isEmpty()) str << QLatin1String("#ifndef ") << symbol << endl; } inline void closeIfndef(QTextStream &str, const QString &symbol) { if (!symbol.isEmpty()) str << QLatin1String("#endif // ") << symbol << endl; } const char *accessibilityDefineC = "QT_NO_ACCESSIBILITY"; const char *toolTipDefineC = "QT_NO_TOOLTIP"; const char *whatsThisDefineC = "QT_NO_WHATSTHIS"; const char *statusTipDefineC = "QT_NO_STATUSTIP"; const char *shortcutDefineC = "QT_NO_SHORTCUT"; } namespace CPP { FontHandle::FontHandle(const DomFont *domFont) : m_domFont(domFont) { } int FontHandle::compare(const FontHandle &rhs) const { const QString family = m_domFont->hasElementFamily() ? m_domFont->elementFamily() : QString(); const QString rhsFamily = rhs.m_domFont->hasElementFamily() ? rhs.m_domFont->elementFamily() : QString(); if (const int frc = family.compare(rhsFamily)) return frc; const int pointSize = m_domFont->hasElementPointSize() ? m_domFont->elementPointSize() : -1; const int rhsPointSize = rhs.m_domFont->hasElementPointSize() ? rhs.m_domFont->elementPointSize() : -1; if (const int crc = compareInt(pointSize, rhsPointSize)) return crc; const int bold = m_domFont->hasElementBold() ? (m_domFont->elementBold() ? 1 : 0) : -1; const int rhsBold = rhs.m_domFont->hasElementBold() ? (rhs.m_domFont->elementBold() ? 1 : 0) : -1; if (const int crc = compareInt(bold, rhsBold)) return crc; const int italic = m_domFont->hasElementItalic() ? (m_domFont->elementItalic() ? 1 : 0) : -1; const int rhsItalic = rhs.m_domFont->hasElementItalic() ? (rhs.m_domFont->elementItalic() ? 1 : 0) : -1; if (const int crc = compareInt(italic, rhsItalic)) return crc; const int underline = m_domFont->hasElementUnderline() ? (m_domFont->elementUnderline() ? 1 : 0) : -1; const int rhsUnderline = rhs.m_domFont->hasElementUnderline() ? (rhs.m_domFont->elementUnderline() ? 1 : 0) : -1; if (const int crc = compareInt(underline, rhsUnderline)) return crc; const int weight = m_domFont->hasElementWeight() ? m_domFont->elementWeight() : -1; const int rhsWeight = rhs.m_domFont->hasElementWeight() ? rhs.m_domFont->elementWeight() : -1; if (const int crc = compareInt(weight, rhsWeight)) return crc; const int strikeOut = m_domFont->hasElementStrikeOut() ? (m_domFont->elementStrikeOut() ? 1 : 0) : -1; const int rhsStrikeOut = rhs.m_domFont->hasElementStrikeOut() ? (rhs.m_domFont->elementStrikeOut() ? 1 : 0) : -1; if (const int crc = compareInt(strikeOut, rhsStrikeOut)) return crc; const int kerning = m_domFont->hasElementKerning() ? (m_domFont->elementKerning() ? 1 : 0) : -1; const int rhsKerning = rhs.m_domFont->hasElementKerning() ? (rhs.m_domFont->elementKerning() ? 1 : 0) : -1; if (const int crc = compareInt(kerning, rhsKerning)) return crc; const int antialiasing = m_domFont->hasElementAntialiasing() ? (m_domFont->elementAntialiasing() ? 1 : 0) : -1; const int rhsAntialiasing = rhs.m_domFont->hasElementAntialiasing() ? (rhs.m_domFont->elementAntialiasing() ? 1 : 0) : -1; if (const int crc = compareInt(antialiasing, rhsAntialiasing)) return crc; const QString styleStrategy = m_domFont->hasElementStyleStrategy() ? m_domFont->elementStyleStrategy() : QString(); const QString rhsStyleStrategy = rhs.m_domFont->hasElementStyleStrategy() ? rhs.m_domFont->elementStyleStrategy() : QString(); if (const int src = styleStrategy.compare(rhsStyleStrategy)) return src; return 0; } IconHandle::IconHandle(const DomResourceIcon *domIcon) : m_domIcon(domIcon) { } int IconHandle::compare(const IconHandle &rhs) const { if (const int comp = m_domIcon->attributeTheme().compare(rhs.m_domIcon->attributeTheme())) return comp; const QString normalOff = m_domIcon->hasElementNormalOff() ? m_domIcon->elementNormalOff()->text() : QString(); const QString rhsNormalOff = rhs.m_domIcon->hasElementNormalOff() ? rhs.m_domIcon->elementNormalOff()->text() : QString(); if (const int comp = normalOff.compare(rhsNormalOff)) return comp; const QString normalOn = m_domIcon->hasElementNormalOn() ? m_domIcon->elementNormalOn()->text() : QString(); const QString rhsNormalOn = rhs.m_domIcon->hasElementNormalOn() ? rhs.m_domIcon->elementNormalOn()->text() : QString(); if (const int comp = normalOn.compare(rhsNormalOn)) return comp; const QString disabledOff = m_domIcon->hasElementDisabledOff() ? m_domIcon->elementDisabledOff()->text() : QString(); const QString rhsDisabledOff = rhs.m_domIcon->hasElementDisabledOff() ? rhs.m_domIcon->elementDisabledOff()->text() : QString(); if (const int comp = disabledOff.compare(rhsDisabledOff)) return comp; const QString disabledOn = m_domIcon->hasElementDisabledOn() ? m_domIcon->elementDisabledOn()->text() : QString(); const QString rhsDisabledOn = rhs.m_domIcon->hasElementDisabledOn() ? rhs.m_domIcon->elementDisabledOn()->text() : QString(); if (const int comp = disabledOn.compare(rhsDisabledOn)) return comp; const QString activeOff = m_domIcon->hasElementActiveOff() ? m_domIcon->elementActiveOff()->text() : QString(); const QString rhsActiveOff = rhs.m_domIcon->hasElementActiveOff() ? rhs.m_domIcon->elementActiveOff()->text() : QString(); if (const int comp = activeOff.compare(rhsActiveOff)) return comp; const QString activeOn = m_domIcon->hasElementActiveOn() ? m_domIcon->elementActiveOn()->text() : QString(); const QString rhsActiveOn = rhs.m_domIcon->hasElementActiveOn() ? rhs.m_domIcon->elementActiveOn()->text() : QString(); if (const int comp = activeOn.compare(rhsActiveOn)) return comp; const QString selectedOff = m_domIcon->hasElementSelectedOff() ? m_domIcon->elementSelectedOff()->text() : QString(); const QString rhsSelectedOff = rhs.m_domIcon->hasElementSelectedOff() ? rhs.m_domIcon->elementSelectedOff()->text() : QString(); if (const int comp = selectedOff.compare(rhsSelectedOff)) return comp; const QString selectedOn = m_domIcon->hasElementSelectedOn() ? m_domIcon->elementSelectedOn()->text() : QString(); const QString rhsSelectedOn = rhs.m_domIcon->hasElementSelectedOn() ? rhs.m_domIcon->elementSelectedOn()->text() : QString(); if (const int comp = selectedOn.compare(rhsSelectedOn)) return comp; // Pre 4.4 Legacy if (const int comp = m_domIcon->text().compare(rhs.m_domIcon->text())) return comp; return 0; } SizePolicyHandle::SizePolicyHandle(const DomSizePolicy *domSizePolicy) : m_domSizePolicy(domSizePolicy) { } int SizePolicyHandle::compare(const SizePolicyHandle &rhs) const { const int hSizeType = m_domSizePolicy->hasElementHSizeType() ? m_domSizePolicy->elementHSizeType() : -1; const int rhsHSizeType = rhs.m_domSizePolicy->hasElementHSizeType() ? rhs.m_domSizePolicy->elementHSizeType() : -1; if (const int crc = compareInt(hSizeType, rhsHSizeType)) return crc; const int vSizeType = m_domSizePolicy->hasElementVSizeType() ? m_domSizePolicy->elementVSizeType() : -1; const int rhsVSizeType = rhs.m_domSizePolicy->hasElementVSizeType() ? rhs.m_domSizePolicy->elementVSizeType() : -1; if (const int crc = compareInt(vSizeType, rhsVSizeType)) return crc; const int hStretch = m_domSizePolicy->hasElementHorStretch() ? m_domSizePolicy->elementHorStretch() : -1; const int rhsHStretch = rhs.m_domSizePolicy->hasElementHorStretch() ? rhs.m_domSizePolicy->elementHorStretch() : -1; if (const int crc = compareInt(hStretch, rhsHStretch)) return crc; const int vStretch = m_domSizePolicy->hasElementVerStretch() ? m_domSizePolicy->elementVerStretch() : -1; const int rhsVStretch = rhs.m_domSizePolicy->hasElementVerStretch() ? rhs.m_domSizePolicy->elementVerStretch() : -1; if (const int crc = compareInt(vStretch, rhsVStretch)) return crc; const QString attributeHSizeType = m_domSizePolicy->hasAttributeHSizeType() ? m_domSizePolicy->attributeHSizeType() : QString(); const QString rhsAttributeHSizeType = rhs.m_domSizePolicy->hasAttributeHSizeType() ? rhs.m_domSizePolicy->attributeHSizeType() : QString(); if (const int hrc = attributeHSizeType.compare(rhsAttributeHSizeType)) return hrc; const QString attributeVSizeType = m_domSizePolicy->hasAttributeVSizeType() ? m_domSizePolicy->attributeVSizeType() : QString(); const QString rhsAttributeVSizeType = rhs.m_domSizePolicy->hasAttributeVSizeType() ? rhs.m_domSizePolicy->attributeVSizeType() : QString(); return attributeVSizeType.compare(rhsAttributeVSizeType); } // --- WriteInitialization: LayoutDefaultHandler WriteInitialization::LayoutDefaultHandler::LayoutDefaultHandler() { std::fill_n(m_state, int(NumProperties), 0u); std::fill_n(m_defaultValues, int(NumProperties), 0); } void WriteInitialization::LayoutDefaultHandler::acceptLayoutDefault(DomLayoutDefault *node) { if (!node) return; if (node->hasAttributeMargin()) { m_state[Margin] |= HasDefaultValue; m_defaultValues[Margin] = node->attributeMargin(); } if (node->hasAttributeSpacing()) { m_state[Spacing] |= HasDefaultValue; m_defaultValues[Spacing] = node->attributeSpacing(); } } void WriteInitialization::LayoutDefaultHandler::acceptLayoutFunction(DomLayoutFunction *node) { if (!node) return; if (node->hasAttributeMargin()) { m_state[Margin] |= HasDefaultFunction; m_functions[Margin] = node->attributeMargin(); m_functions[Margin] += QLatin1String("()"); } if (node->hasAttributeSpacing()) { m_state[Spacing] |= HasDefaultFunction; m_functions[Spacing] = node->attributeSpacing(); m_functions[Spacing] += QLatin1String("()"); } } static inline void writeContentsMargins(const QString &indent, const QString &objectName, int value, QTextStream &str) { QString contentsMargins; QTextStream(&contentsMargins) << value << ", " << value << ", " << value << ", " << value; writeSetter(indent, objectName, QLatin1String("setContentsMargins"), contentsMargins, str); } void WriteInitialization::LayoutDefaultHandler::writeProperty(int p, const QString &indent, const QString &objectName, const DomPropertyMap &properties, const QString &propertyName, const QString &setter, int defaultStyleValue, bool suppressDefault, QTextStream &str) const { // User value if (const DomProperty *prop = properties.value(propertyName)) { const int value = prop->elementNumber(); // Emulate the pre 4.3 behaviour: The value form default value was only used to determine // the default value, layout properties were always written const bool useLayoutFunctionPre43 = !suppressDefault && (m_state[p] == (HasDefaultFunction|HasDefaultValue)) && value == m_defaultValues[p]; if (!useLayoutFunctionPre43) { bool ifndefMac = (!(m_state[p] & (HasDefaultFunction|HasDefaultValue)) && value == defaultStyleValue); if (ifndefMac) str << "#ifndef Q_OS_MAC\n"; if (p == Margin) { // Use setContentsMargins for numeric values writeContentsMargins(indent, objectName, value, str); } else { writeSetter(indent, objectName, setter, value, str); } if (ifndefMac) str << "#endif\n"; return; } } if (suppressDefault) return; // get default. if (m_state[p] & HasDefaultFunction) { // Do not use setContentsMargins to avoid repetitive evaluations. writeSetter(indent, objectName, setter, m_functions[p], str); return; } if (m_state[p] & HasDefaultValue) { if (p == Margin) { // Use setContentsMargins for numeric values writeContentsMargins(indent, objectName, m_defaultValues[p], str); } else { writeSetter(indent, objectName, setter, m_defaultValues[p], str); } } return; } void WriteInitialization::LayoutDefaultHandler::writeProperties(const QString &indent, const QString &varName, const DomPropertyMap &properties, int marginType, bool suppressMarginDefault, QTextStream &str) const { // Write out properties and ignore the ones found in // subsequent writing of the property list. int defaultSpacing = marginType == WriteInitialization::Use43UiFile ? -1 : 6; writeProperty(Spacing, indent, varName, properties, QLatin1String("spacing"), QLatin1String("setSpacing"), defaultSpacing, false, str); // We use 9 as TopLevelMargin, since Designer seem to always use 9. static const int layoutmargins[4] = {-1, 9, 9, 0}; writeProperty(Margin, indent, varName, properties, QLatin1String("margin"), QLatin1String("setMargin"), layoutmargins[marginType], suppressMarginDefault, str); } template // (DomString, DomStringList) static bool needsTranslation(const DomElement *element) { if (!element) return false; return !element->hasAttributeNotr() || !toBool(element->attributeNotr()); } // --- WriteInitialization WriteInitialization::WriteInitialization(Uic *uic) : m_uic(uic), m_driver(uic->driver()), m_output(uic->output()), m_option(uic->option()), m_indent(m_option.indent + m_option.indent), m_dindent(m_indent + m_option.indent), m_stdsetdef(true), m_layoutMarginType(TopLevelMargin), m_mainFormUsedInRetranslateUi(false), m_delayedOut(&m_delayedInitialization, QIODevice::WriteOnly), m_refreshOut(&m_refreshInitialization, QIODevice::WriteOnly), m_actionOut(&m_delayedActionInitialization, QIODevice::WriteOnly), m_layoutWidget(false), m_firstThemeIcon(true) { } void WriteInitialization::acceptUI(DomUI *node) { m_actionGroupChain.push(0); m_widgetChain.push(0); m_layoutChain.push(0); acceptLayoutDefault(node->elementLayoutDefault()); acceptLayoutFunction(node->elementLayoutFunction()); if (node->elementCustomWidgets()) TreeWalker::acceptCustomWidgets(node->elementCustomWidgets()); if (m_option.generateImplemetation) m_output << "#include <" << m_driver->headerFileName() << ">\n\n"; m_stdsetdef = true; if (node->hasAttributeStdSetDef()) m_stdsetdef = node->attributeStdSetDef(); const QString className = node->elementClass() + m_option.postfix; m_generatedClass = className; const QString varName = m_driver->findOrInsertWidget(node->elementWidget()); m_mainFormVarName = varName; m_registeredWidgets.insert(varName, node->elementWidget()); // register the main widget const QString widgetClassName = node->elementWidget()->attributeClass(); m_output << m_option.indent << "void " << "setupUi(" << widgetClassName << " *" << varName << ")\n" << m_option.indent << "{\n"; const QStringList connections = m_uic->databaseInfo()->connections(); for (int i=0; ielementWidget()); if (m_buddies.size() > 0) openIfndef(m_output, QLatin1String(shortcutDefineC)); for (int i=0; isetBuddy(" << b.buddy << ");\n"; } if (m_buddies.size() > 0) closeIfndef(m_output, QLatin1String(shortcutDefineC)); if (node->elementTabStops()) acceptTabStops(node->elementTabStops()); if (m_delayedActionInitialization.size()) m_output << "\n" << m_delayedActionInitialization; m_output << "\n" << m_indent << "retranslateUi(" << varName << ");\n"; if (node->elementConnections()) acceptConnections(node->elementConnections()); if (!m_delayedInitialization.isEmpty()) m_output << "\n" << m_delayedInitialization << "\n"; if (m_option.autoConnection) m_output << "\n" << m_indent << "QMetaObject::connectSlotsByName(" << varName << ");\n"; m_output << m_option.indent << "} // setupUi\n\n"; if (!m_mainFormUsedInRetranslateUi) { m_refreshInitialization += m_indent; m_refreshInitialization += QLatin1String("Q_UNUSED("); m_refreshInitialization += varName ; m_refreshInitialization += QLatin1String(");\n"); } m_output << m_option.indent << "void " << "retranslateUi(" << widgetClassName << " *" << varName << ")\n" << m_option.indent << "{\n" << m_refreshInitialization << m_option.indent << "} // retranslateUi\n\n"; m_layoutChain.pop(); m_widgetChain.pop(); m_actionGroupChain.pop(); } void WriteInitialization::addWizardPage(const QString &pageVarName, const DomWidget *page, const QString &parentWidget) { /* If the node has a (free-format) string "pageId" attribute (which could * an integer or an enumeration value), use setPage(), else addPage(). */ QString id; const auto &attributes = page->elementAttribute(); if (!attributes.empty()) { for (const DomProperty *p : attributes) { if (p->attributeName() == QLatin1String("pageId")) { if (const DomString *ds = p->elementString()) id = ds->text(); break; } } } if (id.isEmpty()) { m_output << m_indent << parentWidget << "->addPage(" << pageVarName << ");\n"; } else { m_output << m_indent << parentWidget << "->setPage(" << id << ", " << pageVarName << ");\n"; } } void WriteInitialization::acceptWidget(DomWidget *node) { m_layoutMarginType = m_widgetChain.count() == 1 ? TopLevelMargin : ChildMargin; const QString className = node->attributeClass(); const QString varName = m_driver->findOrInsertWidget(node); m_registeredWidgets.insert(varName, node); // register the current widget QString parentWidget, parentClass; if (m_widgetChain.top()) { parentWidget = m_driver->findOrInsertWidget(m_widgetChain.top()); parentClass = m_widgetChain.top()->attributeClass(); } const QString savedParentWidget = parentWidget; if (m_uic->isContainer(parentClass)) parentWidget.clear(); if (m_widgetChain.size() != 1) m_output << m_indent << varName << " = new " << m_uic->customWidgetsInfo()->realClassName(className) << '(' << parentWidget << ");\n"; parentWidget = savedParentWidget; if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QComboBox"))) { initializeComboBox(node); } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QListWidget"))) { initializeListWidget(node); } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTreeWidget"))) { initializeTreeWidget(node); } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTableWidget"))) { initializeTableWidget(node); } if (m_uic->isButton(className)) addButtonGroup(node, varName); writeProperties(varName, className, node->elementProperty()); if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QMenu")) && parentWidget.size()) { initializeMenu(node, parentWidget); } if (node->elementLayout().isEmpty()) m_layoutChain.push(0); m_layoutWidget = false; if (className == QLatin1String("QWidget") && !node->hasAttributeNative()) { if (const DomWidget* parentWidget = m_widgetChain.top()) { const QString parentClass = parentWidget->attributeClass(); if (parentClass != QLatin1String("QMainWindow") && !m_uic->isCustomWidgetContainer(parentClass) && !m_uic->isContainer(parentClass)) m_layoutWidget = true; } } m_widgetChain.push(node); m_layoutChain.push(0); TreeWalker::acceptWidget(node); m_layoutChain.pop(); m_widgetChain.pop(); m_layoutWidget = false; const DomPropertyMap attributes = propertyMap(node->elementAttribute()); const QString pageDefaultString = QLatin1String("Page"); if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QMainWindow"))) { if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QMenuBar"))) { m_output << m_indent << parentWidget << "->setMenuBar(" << varName <<");\n"; } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QToolBar"))) { m_output << m_indent << parentWidget << "->addToolBar(" << toolBarAreaStringFromDOMAttributes(attributes) << varName << ");\n"; if (const DomProperty *pbreak = attributes.value(QLatin1String("toolBarBreak"))) { if (pbreak->elementBool() == QLatin1String("true")) { m_output << m_indent << parentWidget << "->insertToolBarBreak(" << varName << ");\n"; } } } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QDockWidget"))) { QString area; if (DomProperty *pstyle = attributes.value(QLatin1String("dockWidgetArea"))) { area += QLatin1String("static_cast("); area += QString::number(pstyle->elementNumber()); area += QLatin1String("), "); } m_output << m_indent << parentWidget << "->addDockWidget(" << area << varName << ");\n"; } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QStatusBar"))) { m_output << m_indent << parentWidget << "->setStatusBar(" << varName << ");\n"; } else { m_output << m_indent << parentWidget << "->setCentralWidget(" << varName << ");\n"; } } // Check for addPageMethod of a custom plugin first const QString addPageMethod = m_uic->customWidgetsInfo()->customWidgetAddPageMethod(parentClass); if (!addPageMethod.isEmpty()) { m_output << m_indent << parentWidget << "->" << addPageMethod << '(' << varName << ");\n"; } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QStackedWidget"))) { m_output << m_indent << parentWidget << "->addWidget(" << varName << ");\n"; } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QToolBar"))) { m_output << m_indent << parentWidget << "->addWidget(" << varName << ");\n"; } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QDockWidget"))) { m_output << m_indent << parentWidget << "->setWidget(" << varName << ");\n"; } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QScrollArea"))) { m_output << m_indent << parentWidget << "->setWidget(" << varName << ");\n"; } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QSplitter"))) { m_output << m_indent << parentWidget << "->addWidget(" << varName << ");\n"; } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QMdiArea"))) { m_output << m_indent << parentWidget << "->addSubWindow(" << varName << ");\n"; } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QWizard"))) { addWizardPage(varName, node, parentWidget); } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QToolBox"))) { QString icon; if (const DomProperty *picon = attributes.value(QLatin1String("icon"))) { icon += QLatin1String(", ") ; icon += iconCall(picon); } const DomProperty *plabel = attributes.value(QLatin1String("label")); DomString *plabelString = plabel ? plabel->elementString() : 0; m_output << m_indent << parentWidget << "->addItem(" << varName << icon << ", " << noTrCall(plabelString, pageDefaultString) << ");\n"; autoTrOutput(plabelString, pageDefaultString) << m_indent << parentWidget << "->setItemText(" << parentWidget << "->indexOf(" << varName << "), " << autoTrCall(plabelString, pageDefaultString) << ");\n"; #ifndef QT_NO_TOOLTIP if (DomProperty *ptoolTip = attributes.value(QLatin1String("toolTip"))) { autoTrOutput(ptoolTip->elementString()) << m_indent << parentWidget << "->setItemToolTip(" << parentWidget << "->indexOf(" << varName << "), " << autoTrCall(ptoolTip->elementString()) << ");\n"; } #endif // QT_NO_TOOLTIP } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QTabWidget"))) { QString icon; if (const DomProperty *picon = attributes.value(QLatin1String("icon"))) { icon += QLatin1String(", "); icon += iconCall(picon); } const DomProperty *ptitle = attributes.value(QLatin1String("title")); DomString *ptitleString = ptitle ? ptitle->elementString() : 0; m_output << m_indent << parentWidget << "->addTab(" << varName << icon << ", " << "QString());\n"; autoTrOutput(ptitleString, pageDefaultString) << m_indent << parentWidget << "->setTabText(" << parentWidget << "->indexOf(" << varName << "), " << autoTrCall(ptitleString, pageDefaultString) << ");\n"; #ifndef QT_NO_TOOLTIP if (const DomProperty *ptoolTip = attributes.value(QLatin1String("toolTip"))) { autoTrOutput(ptoolTip->elementString()) << m_indent << parentWidget << "->setTabToolTip(" << parentWidget << "->indexOf(" << varName << "), " << autoTrCall(ptoolTip->elementString()) << ");\n"; } #endif // QT_NO_TOOLTIP #ifndef QT_NO_WHATSTHIS if (const DomProperty *pwhatsThis = attributes.value(QLatin1String("whatsThis"))) { autoTrOutput(pwhatsThis->elementString()) << m_indent << parentWidget << "->setTabWhatsThis(" << parentWidget << "->indexOf(" << varName << "), " << autoTrCall(pwhatsThis->elementString()) << ");\n"; } #endif // QT_NO_WHATSTHIS } // // Special handling for qtableview/qtreeview fake header attributes // static const QLatin1String realPropertyNames[] = { QLatin1String("visible"), QLatin1String("cascadingSectionResizes"), QLatin1String("defaultSectionSize"), QLatin1String("highlightSections"), QLatin1String("minimumSectionSize"), QLatin1String("showSortIndicator"), QLatin1String("stretchLastSection"), }; if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTreeView")) || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTreeWidget"))) { DomPropertyList headerProperties; for (auto realPropertyName : realPropertyNames) { const QString fakePropertyName = QLatin1String("header") + QChar(realPropertyName.at(0)).toUpper() + realPropertyName.mid(1); if (DomProperty *fakeProperty = attributes.value(fakePropertyName)) { fakeProperty->setAttributeName(realPropertyName); headerProperties << fakeProperty; } } writeProperties(varName + QLatin1String("->header()"), QLatin1String("QHeaderView"), headerProperties, WritePropertyIgnoreObjectName); } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTableView")) || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTableWidget"))) { static const QLatin1String headerPrefixes[] = { QLatin1String("horizontalHeader"), QLatin1String("verticalHeader"), }; for (auto headerPrefix : headerPrefixes) { DomPropertyList headerProperties; for (auto realPropertyName : realPropertyNames) { const QString fakePropertyName = headerPrefix + QChar(realPropertyName.at(0)).toUpper() + realPropertyName.mid(1); if (DomProperty *fakeProperty = attributes.value(fakePropertyName)) { fakeProperty->setAttributeName(realPropertyName); headerProperties << fakeProperty; } } writeProperties(varName + QLatin1String("->") + headerPrefix + QLatin1String("()"), QLatin1String("QHeaderView"), headerProperties, WritePropertyIgnoreObjectName); } } if (node->elementLayout().isEmpty()) m_layoutChain.pop(); const QStringList zOrder = node->elementZOrder(); for (int i = 0; i < zOrder.size(); ++i) { const QString name = zOrder.at(i); if (!m_registeredWidgets.contains(name)) { fprintf(stderr, "%s: Warning: Z-order assignment: '%s' is not a valid widget.\n", qPrintable(m_option.messagePrefix()), name.toLatin1().data()); continue; } if (name.isEmpty()) { continue; } m_output << m_indent << name << "->raise();\n"; } } void WriteInitialization::addButtonGroup(const DomWidget *buttonNode, const QString &varName) { const DomPropertyMap attributes = propertyMap(buttonNode->elementAttribute()); // Look up the button group name as specified in the attribute and find the uniquified name const DomProperty *prop = attributes.value(QLatin1String("buttonGroup")); if (!prop) return; const QString attributeName = toString(prop->elementString()); const DomButtonGroup *group = m_driver->findButtonGroup(attributeName); // Legacy feature: Create missing groups on the fly as the UIC button group feature // was present before the actual Designer support (4.5) const bool createGroupOnTheFly = group == 0; if (createGroupOnTheFly) { DomButtonGroup *newGroup = new DomButtonGroup; newGroup->setAttributeName(attributeName); group = newGroup; fprintf(stderr, "%s: Warning: Creating button group `%s'\n", qPrintable(m_option.messagePrefix()), attributeName.toLatin1().data()); } const QString groupName = m_driver->findOrInsertButtonGroup(group); // Create on demand if (!m_buttonGroups.contains(groupName)) { const QString className = QLatin1String("QButtonGroup"); m_output << m_indent; if (createGroupOnTheFly) m_output << className << " *"; m_output << groupName << " = new " << className << '(' << m_mainFormVarName << ");\n"; m_buttonGroups.insert(groupName); writeProperties(groupName, className, group->elementProperty()); } m_output << m_indent << groupName << "->addButton(" << varName << ");\n"; } void WriteInitialization::acceptLayout(DomLayout *node) { const QString className = node->attributeClass(); const QString varName = m_driver->findOrInsertLayout(node); const DomPropertyMap properties = propertyMap(node->elementProperty()); const bool oldLayoutProperties = properties.value(QLatin1String("margin")) != nullptr; bool isGroupBox = false; m_output << m_indent << varName << " = new " << className << '('; if (!m_layoutChain.top() && !isGroupBox) m_output << m_driver->findOrInsertWidget(m_widgetChain.top()); m_output << ");\n"; // Suppress margin on a read child layout const bool suppressMarginDefault = m_layoutChain.top(); int marginType = Use43UiFile; if (oldLayoutProperties) marginType = m_layoutMarginType; m_LayoutDefaultHandler.writeProperties(m_indent, varName, properties, marginType, suppressMarginDefault, m_output); m_layoutMarginType = SubLayoutMargin; DomPropertyList propList = node->elementProperty(); DomPropertyList newPropList; if (m_layoutWidget) { bool left, top, right, bottom; left = top = right = bottom = false; for (int i = 0; i < propList.size(); ++i) { const DomProperty *p = propList.at(i); const QString propertyName = p->attributeName(); if (propertyName == QLatin1String("leftMargin") && p->kind() == DomProperty::Number) left = true; else if (propertyName == QLatin1String("topMargin") && p->kind() == DomProperty::Number) top = true; else if (propertyName == QLatin1String("rightMargin") && p->kind() == DomProperty::Number) right = true; else if (propertyName == QLatin1String("bottomMargin") && p->kind() == DomProperty::Number) bottom = true; } if (!left) { DomProperty *p = new DomProperty(); p->setAttributeName(QLatin1String("leftMargin")); p->setElementNumber(0); newPropList.append(p); } if (!top) { DomProperty *p = new DomProperty(); p->setAttributeName(QLatin1String("topMargin")); p->setElementNumber(0); newPropList.append(p); } if (!right) { DomProperty *p = new DomProperty(); p->setAttributeName(QLatin1String("rightMargin")); p->setElementNumber(0); newPropList.append(p); } if (!bottom) { DomProperty *p = new DomProperty(); p->setAttributeName(QLatin1String("bottomMargin")); p->setElementNumber(0); newPropList.append(p); } m_layoutWidget = false; } propList.append(newPropList); writeProperties(varName, className, propList, WritePropertyIgnoreMargin|WritePropertyIgnoreSpacing); // Clean up again: propList.clear(); qDeleteAll(newPropList); newPropList.clear(); m_layoutChain.push(node); TreeWalker::acceptLayout(node); m_layoutChain.pop(); // Stretch? (Unless we are compiling for UIC3) const QString numberNull = QString(QLatin1Char('0')); writePropertyList(varName, QLatin1String("setStretch"), node->attributeStretch(), numberNull); writePropertyList(varName, QLatin1String("setRowStretch"), node->attributeRowStretch(), numberNull); writePropertyList(varName, QLatin1String("setColumnStretch"), node->attributeColumnStretch(), numberNull); writePropertyList(varName, QLatin1String("setColumnMinimumWidth"), node->attributeColumnMinimumWidth(), numberNull); writePropertyList(varName, QLatin1String("setRowMinimumHeight"), node->attributeRowMinimumHeight(), numberNull); } // Apply a comma-separated list of values using a function "setSomething(int idx, value)" void WriteInitialization::writePropertyList(const QString &varName, const QString &setFunction, const QString &value, const QString &defaultValue) { if (value.isEmpty()) return; const QStringList list = value.split(QLatin1Char(',')); const int count = list.count(); for (int i = 0; i < count; i++) if (list.at(i) != defaultValue) m_output << m_indent << varName << "->" << setFunction << '(' << i << ", " << list.at(i) << ");\n"; } void WriteInitialization::acceptSpacer(DomSpacer *node) { m_output << m_indent << m_driver->findOrInsertSpacer(node) << " = "; writeSpacerItem(node, m_output); m_output << ";\n"; } static inline QString formLayoutRole(int column, int colspan) { if (colspan > 1) return QLatin1String("QFormLayout::SpanningRole"); return column == 0 ? QLatin1String("QFormLayout::LabelRole") : QLatin1String("QFormLayout::FieldRole"); } void WriteInitialization::acceptLayoutItem(DomLayoutItem *node) { TreeWalker::acceptLayoutItem(node); DomLayout *layout = m_layoutChain.top(); if (!layout) return; const QString layoutName = m_driver->findOrInsertLayout(layout); const QString itemName = m_driver->findOrInsertLayoutItem(node); QString addArgs; QString methodPrefix = QLatin1String("add"); //Consistent API-design galore! if (layout->attributeClass() == QLatin1String("QGridLayout")) { const int row = node->attributeRow(); const int col = node->attributeColumn(); const int rowSpan = node->hasAttributeRowSpan() ? node->attributeRowSpan() : 1; const int colSpan = node->hasAttributeColSpan() ? node->attributeColSpan() : 1; addArgs = QString::fromLatin1("%1, %2, %3, %4, %5").arg(itemName).arg(row).arg(col).arg(rowSpan).arg(colSpan); if (!node->attributeAlignment().isEmpty()) addArgs += QLatin1String(", ") + node->attributeAlignment(); } else { if (layout->attributeClass() == QLatin1String("QFormLayout")) { methodPrefix = QLatin1String("set"); const int row = node->attributeRow(); const int colSpan = node->hasAttributeColSpan() ? node->attributeColSpan() : 1; const QString role = formLayoutRole(node->attributeColumn(), colSpan); addArgs = QString::fromLatin1("%1, %2, %3").arg(row).arg(role, itemName); } else { addArgs = itemName; if (layout->attributeClass().contains(QLatin1String("Box")) && !node->attributeAlignment().isEmpty()) addArgs += QLatin1String(", 0, ") + node->attributeAlignment(); } } // figure out "add" method m_output << "\n" << m_indent << layoutName << "->"; switch (node->kind()) { case DomLayoutItem::Widget: m_output << methodPrefix << "Widget(" << addArgs; break; case DomLayoutItem::Layout: m_output << methodPrefix << "Layout(" << addArgs; break; case DomLayoutItem::Spacer: m_output << methodPrefix << "Item(" << addArgs; break; case DomLayoutItem::Unknown: Q_ASSERT( 0 ); break; } m_output << ");\n\n"; } void WriteInitialization::acceptActionGroup(DomActionGroup *node) { const QString actionName = m_driver->findOrInsertActionGroup(node); QString varName = m_driver->findOrInsertWidget(m_widgetChain.top()); if (m_actionGroupChain.top()) varName = m_driver->findOrInsertActionGroup(m_actionGroupChain.top()); m_output << m_indent << actionName << " = new QActionGroup(" << varName << ");\n"; writeProperties(actionName, QLatin1String("QActionGroup"), node->elementProperty()); m_actionGroupChain.push(node); TreeWalker::acceptActionGroup(node); m_actionGroupChain.pop(); } void WriteInitialization::acceptAction(DomAction *node) { if (node->hasAttributeMenu()) return; const QString actionName = m_driver->findOrInsertAction(node); m_registeredActions.insert(actionName, node); QString varName = m_driver->findOrInsertWidget(m_widgetChain.top()); if (m_actionGroupChain.top()) varName = m_driver->findOrInsertActionGroup(m_actionGroupChain.top()); m_output << m_indent << actionName << " = new QAction(" << varName << ");\n"; writeProperties(actionName, QLatin1String("QAction"), node->elementProperty()); } void WriteInitialization::acceptActionRef(DomActionRef *node) { QString actionName = node->attributeName(); const bool isSeparator = actionName == QLatin1String("separator"); bool isMenu = false; QString varName = m_driver->findOrInsertWidget(m_widgetChain.top()); if (actionName.isEmpty() || !m_widgetChain.top()) { return; } else if (m_driver->actionGroupByName(actionName)) { return; } else if (const DomWidget *w = m_driver->widgetByName(actionName)) { isMenu = m_uic->isMenu(w->attributeClass()); } else if (!(m_driver->actionByName(actionName) || isSeparator)) { fprintf(stderr, "%s: Warning: action `%s' not declared\n", qPrintable(m_option.messagePrefix()), actionName.toLatin1().data()); return; } if (m_widgetChain.top() && isSeparator) { // separator is always reserved! m_actionOut << m_indent << varName << "->addSeparator();\n"; return; } if (isMenu) actionName += QLatin1String("->menuAction()"); m_actionOut << m_indent << varName << "->addAction(" << actionName << ");\n"; } QString WriteInitialization::writeStringListProperty(const DomStringList *list) const { QString propertyValue; QTextStream str(&propertyValue); str << "QStringList()"; const QStringList values = list->elementString(); if (values.isEmpty()) return propertyValue; if (needsTranslation(list)) { const QString comment = list->attributeComment(); for (int i = 0; i < values.size(); ++i) str << '\n' << m_indent << " << " << trCall(values.at(i), comment); } else { for (int i = 0; i < values.size(); ++i) str << " << " << writeString(values.at(i), m_dindent); } return propertyValue; } void WriteInitialization::writeProperties(const QString &varName, const QString &className, const DomPropertyList &lst, unsigned flags) { const bool isTopLevel = m_widgetChain.count() == 1; if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QAxWidget"))) { DomPropertyMap properties = propertyMap(lst); if (DomProperty *p = properties.value(QLatin1String("control"))) { m_output << m_indent << varName << "->setControl(" << writeString(toString(p->elementString()), m_dindent) << ");\n"; } } QString indent; if (!m_widgetChain.top()) { indent = m_option.indent; m_output << m_indent << "if (" << varName << "->objectName().isEmpty())\n"; } if (!(flags & WritePropertyIgnoreObjectName)) m_output << m_indent << indent << varName << "->setObjectName(" << writeString(varName, m_dindent) << ");\n"; int leftMargin, topMargin, rightMargin, bottomMargin; leftMargin = topMargin = rightMargin = bottomMargin = -1; bool frameShadowEncountered = false; for (int i=0; iattributeName(); QString propertyValue; bool delayProperty = false; // special case for the property `geometry': Do not use position if (isTopLevel && propertyName == QLatin1String("geometry") && p->elementRect()) { const DomRect *r = p->elementRect(); m_output << m_indent << varName << "->resize(" << r->elementWidth() << ", " << r->elementHeight() << ");\n"; continue; } else if (propertyName == QLatin1String("currentRow") // QListWidget::currentRow && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QListWidget"))) { m_delayedOut << m_indent << varName << "->setCurrentRow(" << p->elementNumber() << ");\n"; continue; } else if (propertyName == QLatin1String("currentIndex") // set currentIndex later && (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QComboBox")) || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QStackedWidget")) || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTabWidget")) || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QToolBox")))) { m_delayedOut << m_indent << varName << "->setCurrentIndex(" << p->elementNumber() << ");\n"; continue; } else if (propertyName == QLatin1String("tabSpacing") && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QToolBox"))) { m_delayedOut << m_indent << varName << "->layout()->setSpacing(" << p->elementNumber() << ");\n"; continue; } else if (propertyName == QLatin1String("control") // ActiveQt support && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QAxWidget"))) { // already done ;) continue; } else if (propertyName == QLatin1String("default") && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QPushButton"))) { // QTBUG-44406: Setting of QPushButton::default needs to be delayed until the parent is set delayProperty = true; } else if (propertyName == QLatin1String("database") && p->elementStringList()) { // Sql support continue; } else if (propertyName == QLatin1String("frameworkCode") && p->kind() == DomProperty::Bool) { // Sql support continue; } else if (propertyName == QLatin1String("orientation") && m_uic->customWidgetsInfo()->extends(className, QLatin1String("Line"))) { // Line support QString shape = QLatin1String("QFrame::HLine"); if (p->elementEnum() == QLatin1String("Qt::Vertical")) shape = QLatin1String("QFrame::VLine"); m_output << m_indent << varName << "->setFrameShape(" << shape << ");\n"; // QFrame Default is 'Plain'. Make the line 'Sunken' unless otherwise specified if (!frameShadowEncountered) m_output << m_indent << varName << "->setFrameShadow(QFrame::Sunken);\n"; continue; } else if ((flags & WritePropertyIgnoreMargin) && propertyName == QLatin1String("margin")) { continue; } else if ((flags & WritePropertyIgnoreSpacing) && propertyName == QLatin1String("spacing")) { continue; } else if (propertyName == QLatin1String("leftMargin") && p->kind() == DomProperty::Number) { leftMargin = p->elementNumber(); continue; } else if (propertyName == QLatin1String("topMargin") && p->kind() == DomProperty::Number) { topMargin = p->elementNumber(); continue; } else if (propertyName == QLatin1String("rightMargin") && p->kind() == DomProperty::Number) { rightMargin = p->elementNumber(); continue; } else if (propertyName == QLatin1String("bottomMargin") && p->kind() == DomProperty::Number) { bottomMargin = p->elementNumber(); continue; } else if (propertyName == QLatin1String("numDigits") // Deprecated in Qt 4, removed in Qt 5. && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QLCDNumber"))) { qWarning("Widget '%s': Deprecated property QLCDNumber::numDigits encountered. It has been replaced by QLCDNumber::digitCount.", qPrintable(varName)); propertyName = QLatin1String("digitCount"); } else if (propertyName == QLatin1String("frameShadow")) frameShadowEncountered = true; bool stdset = m_stdsetdef; if (p->hasAttributeStdset()) stdset = p->attributeStdset(); QString setFunction; if (stdset) { setFunction = QLatin1String("->set") + propertyName.left(1).toUpper() + propertyName.midRef(1) + QLatin1Char('('); } else { setFunction += QLatin1String("->setProperty(\"") + propertyName + QLatin1String("\", QVariant"); if (p->kind() == DomProperty::Enum) setFunction += QLatin1String("::fromValue"); setFunction += QLatin1Char('('); } QString varNewName = varName; switch (p->kind()) { case DomProperty::Bool: { propertyValue = p->elementBool(); break; } case DomProperty::Color: propertyValue = domColor2QString(p->elementColor()); break; case DomProperty::Cstring: if (propertyName == QLatin1String("buddy") && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QLabel"))) { Buddy buddy = { varName, p->elementCstring() }; m_buddies.append(std::move(buddy)); } else { if (stdset) propertyValue = fixString(p->elementCstring(), m_dindent); else { propertyValue = QLatin1String("QByteArray(") + fixString(p->elementCstring(), m_dindent) + QLatin1Char(')'); } } break; case DomProperty::Cursor: propertyValue = QString::fromLatin1("QCursor(static_cast(%1))") .arg(p->elementCursor()); break; case DomProperty::CursorShape: if (p->hasAttributeStdset() && !p->attributeStdset()) varNewName += QLatin1String("->viewport()"); propertyValue = QString::fromLatin1("QCursor(Qt::%1)") .arg(p->elementCursorShape()); break; case DomProperty::Enum: propertyValue = p->elementEnum(); if (!propertyValue.contains(QLatin1String("::"))) propertyValue = className + QLatin1String("::") + propertyValue; break; case DomProperty::Set: propertyValue = p->elementSet(); break; case DomProperty::Font: propertyValue = writeFontProperties(p->elementFont()); break; case DomProperty::IconSet: propertyValue = writeIconProperties(p->elementIconSet()); break; case DomProperty::Pixmap: propertyValue = pixCall(p); break; case DomProperty::Palette: { const DomPalette *pal = p->elementPalette(); const QString paletteName = m_driver->unique(QLatin1String("palette")); m_output << m_indent << "QPalette " << paletteName << ";\n"; writeColorGroup(pal->elementActive(), QLatin1String("QPalette::Active"), paletteName); writeColorGroup(pal->elementInactive(), QLatin1String("QPalette::Inactive"), paletteName); writeColorGroup(pal->elementDisabled(), QLatin1String("QPalette::Disabled"), paletteName); propertyValue = paletteName; break; } case DomProperty::Point: { const DomPoint *po = p->elementPoint(); propertyValue = QString::fromLatin1("QPoint(%1, %2)") .arg(po->elementX()).arg(po->elementY()); break; } case DomProperty::PointF: { const DomPointF *pof = p->elementPointF(); propertyValue = QString::fromLatin1("QPointF(%1, %2)") .arg(pof->elementX()).arg(pof->elementY()); break; } case DomProperty::Rect: { const DomRect *r = p->elementRect(); propertyValue = QString::fromLatin1("QRect(%1, %2, %3, %4)") .arg(r->elementX()).arg(r->elementY()) .arg(r->elementWidth()).arg(r->elementHeight()); break; } case DomProperty::RectF: { const DomRectF *rf = p->elementRectF(); propertyValue = QString::fromLatin1("QRectF(%1, %2, %3, %4)") .arg(rf->elementX()).arg(rf->elementY()) .arg(rf->elementWidth()).arg(rf->elementHeight()); break; } case DomProperty::Locale: { const DomLocale *locale = p->elementLocale(); propertyValue = QString::fromLatin1("QLocale(QLocale::%1, QLocale::%2)") .arg(locale->attributeLanguage(), locale->attributeCountry()); break; } case DomProperty::SizePolicy: { const QString spName = writeSizePolicy( p->elementSizePolicy()); m_output << m_indent << spName << QString::fromLatin1( ".setHeightForWidth(%1->sizePolicy().hasHeightForWidth());\n") .arg(varName); propertyValue = spName; break; } case DomProperty::Size: { const DomSize *s = p->elementSize(); propertyValue = QString::fromLatin1("QSize(%1, %2)") .arg(s->elementWidth()).arg(s->elementHeight()); break; } case DomProperty::SizeF: { const DomSizeF *sf = p->elementSizeF(); propertyValue = QString::fromLatin1("QSizeF(%1, %2)") .arg(sf->elementWidth()).arg(sf->elementHeight()); break; } case DomProperty::String: { if (propertyName == QLatin1String("objectName")) { const QString v = p->elementString()->text(); if (v == varName) break; // ### qWarning("Deprecated: the property `objectName' is different from the variable name"); } propertyValue = autoTrCall(p->elementString()); break; } case DomProperty::Number: propertyValue = QString::number(p->elementNumber()); break; case DomProperty::UInt: propertyValue = QString::number(p->elementUInt()); propertyValue += QLatin1Char('u'); break; case DomProperty::LongLong: propertyValue = QLatin1String("Q_INT64_C("); propertyValue += QString::number(p->elementLongLong()); propertyValue += QLatin1Char(')');; break; case DomProperty::ULongLong: propertyValue = QLatin1String("Q_UINT64_C("); propertyValue += QString::number(p->elementULongLong()); propertyValue += QLatin1Char(')'); break; case DomProperty::Float: propertyValue = QString::number(p->elementFloat()); break; case DomProperty::Double: propertyValue = QString::number(p->elementDouble()); break; case DomProperty::Char: { const DomChar *c = p->elementChar(); propertyValue = QString::fromLatin1("QChar(%1)") .arg(c->elementUnicode()); break; } case DomProperty::Date: { const DomDate *d = p->elementDate(); propertyValue = QString::fromLatin1("QDate(%1, %2, %3)") .arg(d->elementYear()) .arg(d->elementMonth()) .arg(d->elementDay()); break; } case DomProperty::Time: { const DomTime *t = p->elementTime(); propertyValue = QString::fromLatin1("QTime(%1, %2, %3)") .arg(t->elementHour()) .arg(t->elementMinute()) .arg(t->elementSecond()); break; } case DomProperty::DateTime: { const DomDateTime *dt = p->elementDateTime(); propertyValue = QString::fromLatin1("QDateTime(QDate(%1, %2, %3), QTime(%4, %5, %6))") .arg(dt->elementYear()) .arg(dt->elementMonth()) .arg(dt->elementDay()) .arg(dt->elementHour()) .arg(dt->elementMinute()) .arg(dt->elementSecond()); break; } case DomProperty::StringList: propertyValue = writeStringListProperty(p->elementStringList()); break; case DomProperty::Url: { const DomUrl* u = p->elementUrl(); propertyValue = QString::fromLatin1("QUrl(%1)") .arg(writeString(u->elementString()->text(), m_dindent)); break; } case DomProperty::Brush: propertyValue = writeBrushInitialization(p->elementBrush()); break; case DomProperty::Unknown: break; } if (propertyValue.size()) { const char* defineC = 0; if (propertyName == QLatin1String("toolTip")) defineC = toolTipDefineC; else if (propertyName == QLatin1String("whatsThis")) defineC = whatsThisDefineC; else if (propertyName == QLatin1String("statusTip")) defineC = statusTipDefineC; else if (propertyName == QLatin1String("shortcut")) defineC = shortcutDefineC; else if (propertyName == QLatin1String("accessibleName") || propertyName == QLatin1String("accessibleDescription")) defineC = accessibilityDefineC; QTextStream &o = delayProperty ? m_delayedOut : autoTrOutput(p); if (defineC) openIfndef(o, QLatin1String(defineC)); o << m_indent << varNewName << setFunction << propertyValue; if (!stdset) o << ')'; o << ");\n"; if (defineC) closeIfndef(o, QLatin1String(defineC)); if (varName == m_mainFormVarName && &o == &m_refreshOut) { // this is the only place (currently) where we output mainForm name to the retranslateUi(). // Other places output merely instances of a certain class (which cannot be main form, e.g. QListWidget). m_mainFormUsedInRetranslateUi = true; } } } if (leftMargin != -1 || topMargin != -1 || rightMargin != -1 || bottomMargin != -1) { m_output << m_indent << varName << QLatin1String("->setContentsMargins(") << leftMargin << QLatin1String(", ") << topMargin << QLatin1String(", ") << rightMargin << QLatin1String(", ") << bottomMargin << QLatin1String(");\n"); } } QString WriteInitialization::writeSizePolicy(const DomSizePolicy *sp) { // check cache const SizePolicyHandle sizePolicyHandle(sp); const SizePolicyNameMap::const_iterator it = m_sizePolicyNameMap.constFind(sizePolicyHandle); if ( it != m_sizePolicyNameMap.constEnd()) { return it.value(); } // insert with new name const QString spName = m_driver->unique(QLatin1String("sizePolicy")); m_sizePolicyNameMap.insert(sizePolicyHandle, spName); m_output << m_indent << "QSizePolicy " << spName; do { if (sp->hasElementHSizeType() && sp->hasElementVSizeType()) { m_output << "(static_cast(" << sp->elementHSizeType() << "), static_cast(" << sp->elementVSizeType() << "));\n"; break; } if (sp->hasAttributeHSizeType() && sp->hasAttributeVSizeType()) { m_output << "(QSizePolicy::" << sp->attributeHSizeType() << ", QSizePolicy::" << sp->attributeVSizeType() << ");\n"; break; } m_output << ";\n"; } while (false); m_output << m_indent << spName << ".setHorizontalStretch(" << sp->elementHorStretch() << ");\n"; m_output << m_indent << spName << ".setVerticalStretch(" << sp->elementVerStretch() << ");\n"; return spName; } // Check for a font with the given properties in the FontPropertiesNameMap // or create a new one. Returns the name. QString WriteInitialization::writeFontProperties(const DomFont *f) { // check cache const FontHandle fontHandle(f); const FontPropertiesNameMap::const_iterator it = m_fontPropertiesNameMap.constFind(fontHandle); if ( it != m_fontPropertiesNameMap.constEnd()) { return it.value(); } // insert with new name const QString fontName = m_driver->unique(QLatin1String("font")); m_fontPropertiesNameMap.insert(FontHandle(f), fontName); m_output << m_indent << "QFont " << fontName << ";\n"; if (f->hasElementFamily() && !f->elementFamily().isEmpty()) { m_output << m_indent << fontName << ".setFamily(" << writeString(f->elementFamily(), m_dindent) << ");\n"; } if (f->hasElementPointSize() && f->elementPointSize() > 0) { m_output << m_indent << fontName << ".setPointSize(" << f->elementPointSize() << ");\n"; } if (f->hasElementBold()) { m_output << m_indent << fontName << ".setBold(" << (f->elementBold() ? "true" : "false") << ");\n"; } if (f->hasElementItalic()) { m_output << m_indent << fontName << ".setItalic(" << (f->elementItalic() ? "true" : "false") << ");\n"; } if (f->hasElementUnderline()) { m_output << m_indent << fontName << ".setUnderline(" << (f->elementUnderline() ? "true" : "false") << ");\n"; } if (f->hasElementWeight() && f->elementWeight() > 0) { m_output << m_indent << fontName << ".setWeight(" << f->elementWeight() << ");" << endl; } if (f->hasElementStrikeOut()) { m_output << m_indent << fontName << ".setStrikeOut(" << (f->elementStrikeOut() ? "true" : "false") << ");\n"; } if (f->hasElementKerning()) { m_output << m_indent << fontName << ".setKerning(" << (f->elementKerning() ? "true" : "false") << ");\n"; } if (f->hasElementAntialiasing()) { m_output << m_indent << fontName << ".setStyleStrategy(" << (f->elementAntialiasing() ? "QFont::PreferDefault" : "QFont::NoAntialias") << ");\n"; } if (f->hasElementStyleStrategy()) { m_output << m_indent << fontName << ".setStyleStrategy(QFont::" << f->elementStyleStrategy() << ");\n"; } return fontName; } // Post 4.4 write resource icon static void writeResourceIcon(QTextStream &output, const QString &iconName, const QString &indent, const DomResourceIcon *i) { if (i->hasElementNormalOff()) output << indent << iconName << ".addFile(" << writeString(i->elementNormalOff()->text(), indent) << ", QSize(), QIcon::Normal, QIcon::Off);\n"; if (i->hasElementNormalOn()) output << indent << iconName << ".addFile(" << writeString(i->elementNormalOn()->text(), indent) << ", QSize(), QIcon::Normal, QIcon::On);\n"; if (i->hasElementDisabledOff()) output << indent << iconName << ".addFile(" << writeString(i->elementDisabledOff()->text(), indent) << ", QSize(), QIcon::Disabled, QIcon::Off);\n"; if (i->hasElementDisabledOn()) output << indent << iconName << ".addFile(" << writeString(i->elementDisabledOn()->text(), indent) << ", QSize(), QIcon::Disabled, QIcon::On);\n"; if (i->hasElementActiveOff()) output << indent << iconName << ".addFile(" << writeString(i->elementActiveOff()->text(), indent) << ", QSize(), QIcon::Active, QIcon::Off);\n"; if (i->hasElementActiveOn()) output << indent << iconName << ".addFile(" << writeString(i->elementActiveOn()->text(), indent) << ", QSize(), QIcon::Active, QIcon::On);\n"; if (i->hasElementSelectedOff()) output << indent << iconName << ".addFile(" << writeString(i->elementSelectedOff()->text(), indent) << ", QSize(), QIcon::Selected, QIcon::Off);\n"; if (i->hasElementSelectedOn()) output << indent << iconName << ".addFile(" << writeString(i->elementSelectedOn()->text(), indent) << ", QSize(), QIcon::Selected, QIcon::On);\n"; } QString WriteInitialization::writeIconProperties(const DomResourceIcon *i) { // check cache const IconHandle iconHandle(i); const IconPropertiesNameMap::const_iterator it = m_iconPropertiesNameMap.constFind(iconHandle); if (it != m_iconPropertiesNameMap.constEnd()) { return it.value(); } // insert with new name const QString iconName = m_driver->unique(QLatin1String("icon")); m_iconPropertiesNameMap.insert(IconHandle(i), iconName); if (isIconFormat44(i)) { if (i->attributeTheme().isEmpty()) { // No theme: Write resource icon as is m_output << m_indent << "QIcon " << iconName << ";\n"; writeResourceIcon(m_output, iconName, m_indent, i); } else { // Theme: Generate code to check the theme and default to resource const QString themeIconName = writeString(i->attributeTheme(), QString()); if (iconHasStatePixmaps(i)) { // Theme + default state pixmaps: // Generate code to check the theme and default to state pixmaps m_output << m_indent << "QIcon " << iconName << ";\n"; const char themeNameStringVariableC[] = "iconThemeName"; // Store theme name in a variable m_output << m_indent; if (m_firstThemeIcon) { // Declare variable string m_output << "QString "; m_firstThemeIcon = false; } m_output << themeNameStringVariableC << " = " << themeIconName << ";\n"; m_output << m_indent << "if (QIcon::hasThemeIcon(" << themeNameStringVariableC << ")) {\n" << m_dindent << iconName << " = QIcon::fromTheme(" << themeNameStringVariableC << ");\n" << m_indent << "} else {\n"; writeResourceIcon(m_output, iconName, m_dindent, i); m_output << m_indent << "}\n"; } else { // Theme, but no state pixmaps: Construct from theme directly. m_output << m_indent << "QIcon " << iconName << "(QIcon::fromTheme(" << themeIconName << "));\n"; } // Theme, but not state } // >= 4.4 } else { // pre-4.4 legacy m_output << m_indent << "const QIcon " << iconName << " = " << pixCall(QLatin1String("QIcon"), i->text())<< ";\n"; } return iconName; } QString WriteInitialization::domColor2QString(const DomColor *c) { if (c->hasAttributeAlpha()) return QString::fromLatin1("QColor(%1, %2, %3, %4)") .arg(c->elementRed()) .arg(c->elementGreen()) .arg(c->elementBlue()) .arg(c->attributeAlpha()); return QString::fromLatin1("QColor(%1, %2, %3)") .arg(c->elementRed()) .arg(c->elementGreen()) .arg(c->elementBlue()); } void WriteInitialization::writeColorGroup(DomColorGroup *colorGroup, const QString &group, const QString &paletteName) { if (!colorGroup) return; // old format const auto &colors = colorGroup->elementColor(); for (int i=0; i(" << QString::number(i) << ')' << ", " << domColor2QString(color) << ");\n"; } // new format const auto &colorRoles = colorGroup->elementColorRole(); for (const DomColorRole *colorRole : colorRoles) { if (colorRole->hasAttributeRole()) { const QString brushName = writeBrushInitialization(colorRole->elementBrush()); m_output << m_indent << paletteName << ".setBrush(" << group << ", " << "QPalette::" << colorRole->attributeRole() << ", " << brushName << ");\n"; } } } // Write initialization for brush unless it is found in the cache. Returns the name to use // in an expression. QString WriteInitialization::writeBrushInitialization(const DomBrush *brush) { // Simple solid, colored brushes are cached const bool solidColoredBrush = !brush->hasAttributeBrushStyle() || brush->attributeBrushStyle() == QLatin1String("SolidPattern"); uint rgb = 0; if (solidColoredBrush) { if (const DomColor *color = brush->elementColor()) { rgb = ((color->elementRed() & 0xFF) << 24) | ((color->elementGreen() & 0xFF) << 16) | ((color->elementBlue() & 0xFF) << 8) | ((color->attributeAlpha() & 0xFF)); const ColorBrushHash::const_iterator cit = m_colorBrushHash.constFind(rgb); if (cit != m_colorBrushHash.constEnd()) return cit.value(); } } // Create and enter into cache if simple const QString brushName = m_driver->unique(QLatin1String("brush")); writeBrush(brush, brushName); if (solidColoredBrush) m_colorBrushHash.insert(rgb, brushName); return brushName; } void WriteInitialization::writeBrush(const DomBrush *brush, const QString &brushName) { QString style = QLatin1String("SolidPattern"); if (brush->hasAttributeBrushStyle()) style = brush->attributeBrushStyle(); if (style == QLatin1String("LinearGradientPattern") || style == QLatin1String("RadialGradientPattern") || style == QLatin1String("ConicalGradientPattern")) { const DomGradient *gradient = brush->elementGradient(); const QString gradientType = gradient->attributeType(); const QString gradientName = m_driver->unique(QLatin1String("gradient")); if (gradientType == QLatin1String("LinearGradient")) { m_output << m_indent << "QLinearGradient " << gradientName << '(' << gradient->attributeStartX() << ", " << gradient->attributeStartY() << ", " << gradient->attributeEndX() << ", " << gradient->attributeEndY() << ");\n"; } else if (gradientType == QLatin1String("RadialGradient")) { m_output << m_indent << "QRadialGradient " << gradientName << '(' << gradient->attributeCentralX() << ", " << gradient->attributeCentralY() << ", " << gradient->attributeRadius() << ", " << gradient->attributeFocalX() << ", " << gradient->attributeFocalY() << ");\n"; } else if (gradientType == QLatin1String("ConicalGradient")) { m_output << m_indent << "QConicalGradient " << gradientName << '(' << gradient->attributeCentralX() << ", " << gradient->attributeCentralY() << ", " << gradient->attributeAngle() << ");\n"; } m_output << m_indent << gradientName << ".setSpread(QGradient::" << gradient->attributeSpread() << ");\n"; if (gradient->hasAttributeCoordinateMode()) { m_output << m_indent << gradientName << ".setCoordinateMode(QGradient::" << gradient->attributeCoordinateMode() << ");\n"; } const auto &stops = gradient->elementGradientStop(); for (const DomGradientStop *stop : stops) { const DomColor *color = stop->elementColor(); m_output << m_indent << gradientName << ".setColorAt(" << stop->attributePosition() << ", " << domColor2QString(color) << ");\n"; } m_output << m_indent << "QBrush " << brushName << '(' << gradientName << ");\n"; } else if (style == QLatin1String("TexturePattern")) { const DomProperty *property = brush->elementTexture(); const QString iconValue = iconCall(property); m_output << m_indent << "QBrush " << brushName << " = QBrush(" << iconValue << ");\n"; } else { const DomColor *color = brush->elementColor(); m_output << m_indent << "QBrush " << brushName << '(' << domColor2QString(color) << ");\n"; m_output << m_indent << brushName << ".setStyle(" << "Qt::" << style << ");\n"; } } void WriteInitialization::acceptCustomWidget(DomCustomWidget *node) { Q_UNUSED(node); } void WriteInitialization::acceptCustomWidgets(DomCustomWidgets *node) { Q_UNUSED(node); } void WriteInitialization::acceptTabStops(DomTabStops *tabStops) { QString lastName; const QStringList l = tabStops->elementTabStop(); for (int i=0; ikind() == DomProperty::IconSet) return writeIconProperties(icon->elementIconSet()); return pixCall(icon); } QString WriteInitialization::pixCall(const DomProperty *p) const { QString type, s; switch (p->kind()) { case DomProperty::IconSet: type = QLatin1String("QIcon"); s = p->elementIconSet()->text(); break; case DomProperty::Pixmap: type = QLatin1String("QPixmap"); s = p->elementPixmap()->text(); break; default: qWarning("%s: Warning: Unknown icon format encountered. The ui-file was generated with a too-recent version of Designer.", qPrintable(m_option.messagePrefix())); return QLatin1String("QIcon()"); break; } return pixCall(type, s); } QString WriteInitialization::pixCall(const QString &t, const QString &text) const { QString type = t; if (text.isEmpty()) { type += QLatin1String("()"); return type; } QString pixFunc = m_uic->pixmapFunction(); if (pixFunc.isEmpty()) pixFunc = QLatin1String("QString::fromUtf8"); type += QLatin1Char('(') + pixFunc + QLatin1Char('(') + fixString(text, m_dindent) + QLatin1String("))"); return type; } void WriteInitialization::initializeComboBox(DomWidget *w) { const QString varName = m_driver->findOrInsertWidget(w); const QString className = w->attributeClass(); const auto &items = w->elementItem(); if (items.isEmpty()) return; // If possible use qcombobox's addItems() which is much faster then a bunch of addItem() calls bool makeStringListCall = true; bool translatable = false; QStringList list; for (int i=0; ielementProperty()); const DomProperty *text = properties.value(QLatin1String("text")); const DomProperty *pixmap = properties.value(QLatin1String("icon")); bool needsTr = needsTranslation(text->elementString()); if (pixmap != 0 || (i > 0 && translatable != needsTr)) { makeStringListCall = false; break; } translatable = needsTr; list.append(autoTrCall(text->elementString())); // fix me here } if (makeStringListCall) { QTextStream &o = translatable ? m_refreshOut : m_output; if (translatable) o << m_indent << varName << "->clear();\n"; o << m_indent << varName << "->insertItems(0, QStringList()" << '\n'; for (int i = 0; i < list.size(); ++i) o << m_indent << " << " << list.at(i) << "\n"; o << m_indent << ");\n"; } else { for (int i = 0; i < items.size(); ++i) { const DomItem *item = items.at(i); const DomPropertyMap properties = propertyMap(item->elementProperty()); const DomProperty *text = properties.value(QLatin1String("text")); const DomProperty *icon = properties.value(QLatin1String("icon")); QString iconValue; if (icon) iconValue = iconCall(icon); m_output << m_indent << varName << "->addItem("; if (icon) m_output << iconValue << ", "; if (needsTranslation(text->elementString())) { m_output << "QString());\n"; m_refreshOut << m_indent << varName << "->setItemText(" << i << ", " << trCall(text->elementString()) << ");\n"; } else { m_output << noTrCall(text->elementString()) << ");\n"; } } m_refreshOut << "\n"; } } QString WriteInitialization::disableSorting(DomWidget *w, const QString &varName) { // turn off sortingEnabled to force programmatic item order (setItem()) QString tempName; if (!w->elementItem().isEmpty()) { tempName = m_driver->unique(QLatin1String("__sortingEnabled")); m_refreshOut << "\n"; m_refreshOut << m_indent << "const bool " << tempName << " = " << varName << "->isSortingEnabled();\n"; m_refreshOut << m_indent << varName << "->setSortingEnabled(false);\n"; } return tempName; } void WriteInitialization::enableSorting(DomWidget *w, const QString &varName, const QString &tempName) { if (!w->elementItem().isEmpty()) { m_refreshOut << m_indent << varName << "->setSortingEnabled(" << tempName << ");\n\n"; } } /* * Initializers are just strings containing the function call and need to be prepended * the line indentation and the object they are supposed to initialize. * String initializers come with a preprocessor conditional (ifdef), so the code * compiles with QT_NO_xxx. A null pointer means no conditional. String initializers * are written to the retranslateUi() function, others to setupUi(). */ /*! Create non-string inititializer. \param value the value to initialize the attribute with. May be empty, in which case the initializer is omitted. See above for other parameters. */ void WriteInitialization::addInitializer(Item *item, const QString &name, int column, const QString &value, const QString &directive, bool translatable) const { if (!value.isEmpty()) item->addSetter(QLatin1String("->set") + name.at(0).toUpper() + name.midRef(1) + QLatin1Char('(') + (column < 0 ? QString() : QString::number(column) + QLatin1String(", ")) + value + QLatin1String(");"), directive, translatable); } /*! Create string inititializer. \param initializers in/out list of inializers \param properties map property name -> property to extract data from \param name the property to extract \param col the item column to generate the initializer for. This is relevant for tree widgets only. If it is -1, no column index will be generated. \param ifdef preprocessor symbol for disabling compilation of this initializer */ void WriteInitialization::addStringInitializer(Item *item, const DomPropertyMap &properties, const QString &name, int column, const QString &directive) const { if (const DomProperty *p = properties.value(name)) { DomString *str = p->elementString(); QString text = toString(str); if (!text.isEmpty()) { bool translatable = needsTranslation(str); QString value = autoTrCall(str); addInitializer(item, name, column, value, directive, translatable); } } } void WriteInitialization::addBrushInitializer(Item *item, const DomPropertyMap &properties, const QString &name, int column) { if (const DomProperty *p = properties.value(name)) { if (p->elementBrush()) addInitializer(item, name, column, writeBrushInitialization(p->elementBrush())); else if (p->elementColor()) addInitializer(item, name, column, domColor2QString(p->elementColor())); } } /*! Create inititializer for a flag value in the Qt namespace. If the named property is not in the map, the initializer is omitted. */ void WriteInitialization::addQtFlagsInitializer(Item *item, const DomPropertyMap &properties, const QString &name, int column) const { if (const DomProperty *p = properties.value(name)) { QString v = p->elementSet(); if (!v.isEmpty()) { v.replace(QLatin1Char('|'), QLatin1String("|Qt::")); addInitializer(item, name, column, QLatin1String("Qt::") + v); } } } /*! Create inititializer for an enum value in the Qt namespace. If the named property is not in the map, the initializer is omitted. */ void WriteInitialization::addQtEnumInitializer(Item *item, const DomPropertyMap &properties, const QString &name, int column) const { if (const DomProperty *p = properties.value(name)) { QString v = p->elementEnum(); if (!v.isEmpty()) addInitializer(item, name, column, QLatin1String("Qt::") + v); } } /*! Create inititializers for all common properties that may be bound to a column. */ void WriteInitialization::addCommonInitializers(Item *item, const DomPropertyMap &properties, int column) { if (const DomProperty *icon = properties.value(QLatin1String("icon"))) addInitializer(item, QLatin1String("icon"), column, iconCall(icon)); addBrushInitializer(item, properties, QLatin1String("foreground"), column); addBrushInitializer(item, properties, QLatin1String("background"), column); if (const DomProperty *font = properties.value(QLatin1String("font"))) addInitializer(item, QLatin1String("font"), column, writeFontProperties(font->elementFont())); addQtFlagsInitializer(item, properties, QLatin1String("textAlignment"), column); addQtEnumInitializer(item, properties, QLatin1String("checkState"), column); addStringInitializer(item, properties, QLatin1String("text"), column); addStringInitializer(item, properties, QLatin1String("toolTip"), column, QLatin1String(toolTipDefineC)); addStringInitializer(item, properties, QLatin1String("whatsThis"), column, QLatin1String(whatsThisDefineC)); addStringInitializer(item, properties, QLatin1String("statusTip"), column, QLatin1String(statusTipDefineC)); } void WriteInitialization::initializeListWidget(DomWidget *w) { const QString varName = m_driver->findOrInsertWidget(w); const QString className = w->attributeClass(); const auto &items = w->elementItem(); if (items.isEmpty()) return; QString tempName = disableSorting(w, varName); // items // TODO: the generated code should be data-driven to reduce its size for (int i = 0; i < items.size(); ++i) { const DomItem *domItem = items.at(i); const DomPropertyMap properties = propertyMap(domItem->elementProperty()); Item item(QLatin1String("QListWidgetItem"), m_indent, m_output, m_refreshOut, m_driver); addQtFlagsInitializer(&item, properties, QLatin1String("flags")); addCommonInitializers(&item, properties); item.writeSetupUi(varName); item.writeRetranslateUi(varName + QLatin1String("->item(") + QString::number(i) + QLatin1Char(')')); } enableSorting(w, varName, tempName); } void WriteInitialization::initializeTreeWidget(DomWidget *w) { const QString varName = m_driver->findOrInsertWidget(w); // columns Item item(QLatin1String("QTreeWidgetItem"), m_indent, m_output, m_refreshOut, m_driver); const auto &columns = w->elementColumn(); for (int i = 0; i < columns.size(); ++i) { const DomColumn *column = columns.at(i); const DomPropertyMap properties = propertyMap(column->elementProperty()); addCommonInitializers(&item, properties, i); if (const DomProperty *p = properties.value(QLatin1String("text"))) { DomString *str = p->elementString(); if (str && str->text().isEmpty()) m_output << m_indent << varName << "->headerItem()->setText(" << i << ", QString());\n"; } } const QString itemName = item.writeSetupUi(QString(), Item::DontConstruct); item.writeRetranslateUi(varName + QLatin1String("->headerItem()")); if (!itemName.isNull()) m_output << m_indent << varName << "->setHeaderItem(" << itemName << ");\n"; if (w->elementItem().size() == 0) return; QString tempName = disableSorting(w, varName); QList items = initializeTreeWidgetItems(w->elementItem()); for (int i = 0; i < items.count(); i++) { Item *itm = items[i]; itm->writeSetupUi(varName); itm->writeRetranslateUi(varName + QLatin1String("->topLevelItem(") + QString::number(i) + QLatin1Char(')')); delete itm; } enableSorting(w, varName, tempName); } /*! Create and write out initializers for tree widget items. This function makes sure that only needed items are fetched (subject to preprocessor conditionals), that each item is fetched from its parent widget/item exactly once and that no temporary variables are created for items that are needed only once. As fetches are built top-down from the root, but determining how often and under which conditions an item is needed needs to be done bottom-up, the whole process makes two passes, storing the intermediate result in a recursive StringInitializerListMap. */ QList WriteInitialization::initializeTreeWidgetItems(const QVector &domItems) { // items QList items; const int numDomItems = domItems.size(); items.reserve(numDomItems); for (int i = 0; i < numDomItems; ++i) { const DomItem *domItem = domItems.at(i); Item *item = new Item(QLatin1String("QTreeWidgetItem"), m_indent, m_output, m_refreshOut, m_driver); items << item; QHash map; int col = -1; const DomPropertyList properties = domItem->elementProperty(); for (int j = 0; j < properties.size(); ++j) { DomProperty *p = properties.at(j); if (p->attributeName() == QLatin1String("text")) { if (!map.isEmpty()) { addCommonInitializers(item, map, col); map.clear(); } col++; } map.insert(p->attributeName(), p); } addCommonInitializers(item, map, col); // AbstractFromBuilder saves flags last, so they always end up in the last column's map. addQtFlagsInitializer(item, map, QLatin1String("flags")); const QList subItems = initializeTreeWidgetItems(domItem->elementItem()); for (Item *subItem : subItems) item->addChild(subItem); } return items; } void WriteInitialization::initializeTableWidget(DomWidget *w) { const QString varName = m_driver->findOrInsertWidget(w); // columns const auto &columns = w->elementColumn(); if (columns.size() != 0) { m_output << m_indent << "if (" << varName << "->columnCount() < " << columns.size() << ")\n" << m_dindent << varName << "->setColumnCount(" << columns.size() << ");\n"; } for (int i = 0; i < columns.size(); ++i) { const DomColumn *column = columns.at(i); if (!column->elementProperty().isEmpty()) { const DomPropertyMap properties = propertyMap(column->elementProperty()); Item item(QLatin1String("QTableWidgetItem"), m_indent, m_output, m_refreshOut, m_driver); addCommonInitializers(&item, properties); QString itemName = item.writeSetupUi(QString(), Item::ConstructItemAndVariable); item.writeRetranslateUi(varName + QLatin1String("->horizontalHeaderItem(") + QString::number(i) + QLatin1Char(')')); m_output << m_indent << varName << "->setHorizontalHeaderItem(" << QString::number(i) << ", " << itemName << ");\n"; } } // rows const auto &rows = w->elementRow(); if (rows.size() != 0) { m_output << m_indent << "if (" << varName << "->rowCount() < " << rows.size() << ")\n" << m_dindent << varName << "->setRowCount(" << rows.size() << ");\n"; } for (int i = 0; i < rows.size(); ++i) { const DomRow *row = rows.at(i); if (!row->elementProperty().isEmpty()) { const DomPropertyMap properties = propertyMap(row->elementProperty()); Item item(QLatin1String("QTableWidgetItem"), m_indent, m_output, m_refreshOut, m_driver); addCommonInitializers(&item, properties); QString itemName = item.writeSetupUi(QString(), Item::ConstructItemAndVariable); item.writeRetranslateUi(varName + QLatin1String("->verticalHeaderItem(") + QString::number(i) + QLatin1Char(')')); m_output << m_indent << varName << "->setVerticalHeaderItem(" << QString::number(i) << ", " << itemName << ");\n"; } } // items QString tempName = disableSorting(w, varName); const auto &items = w->elementItem(); for (int i = 0; i < items.size(); ++i) { const DomItem *cell = items.at(i); if (cell->hasAttributeRow() && cell->hasAttributeColumn() && !cell->elementProperty().isEmpty()) { const int r = cell->attributeRow(); const int c = cell->attributeColumn(); const DomPropertyMap properties = propertyMap(cell->elementProperty()); Item item(QLatin1String("QTableWidgetItem"), m_indent, m_output, m_refreshOut, m_driver); addQtFlagsInitializer(&item, properties, QLatin1String("flags")); addCommonInitializers(&item, properties); QString itemName = item.writeSetupUi(QString(), Item::ConstructItemAndVariable); item.writeRetranslateUi(varName + QLatin1String("->item(") + QString::number(r) + QLatin1String(", ") + QString::number(c) + QLatin1Char(')')); m_output << m_indent << varName << "->setItem(" << QString::number(r) << ", " << QString::number(c) << ", " << itemName << ");\n"; } } enableSorting(w, varName, tempName); } QString WriteInitialization::trCall(const QString &str, const QString &commentHint) const { if (str.isEmpty()) return QLatin1String("QString()"); QString result; const QString comment = commentHint.isEmpty() ? QString(QLatin1String("Q_NULLPTR")) : fixString(commentHint, m_dindent); if (m_option.translateFunction.isEmpty()) { if (m_option.idBased) { result += QLatin1String("qtTrId("); } else { result += QLatin1String("QApplication::translate(\"") + m_generatedClass + QLatin1String("\", "); } } else { result += m_option.translateFunction + QLatin1Char('('); } result += fixString(str, m_dindent); if (!m_option.idBased) { result += QLatin1String(", ") + comment; } result += QLatin1Char(')'); return result; } void WriteInitialization::initializeMenu(DomWidget *w, const QString &/*parentWidget*/) { const QString menuName = m_driver->findOrInsertWidget(w); const QString menuAction = menuName + QLatin1String("Action"); const DomAction *action = m_driver->actionByName(menuAction); if (action && action->hasAttributeMenu()) { m_output << m_indent << menuAction << " = " << menuName << "->menuAction();\n"; } } QString WriteInitialization::trCall(DomString *str, const QString &defaultString) const { QString value = defaultString; QString comment; if (str) { value = toString(str); comment = str->attributeComment(); } return trCall(value, comment); } QString WriteInitialization::noTrCall(DomString *str, const QString &defaultString) const { QString value = defaultString; if (!str && defaultString.isEmpty()) return QString(); if (str) value = str->text(); return writeString(value, m_dindent); } QString WriteInitialization::autoTrCall(DomString *str, const QString &defaultString) const { if ((!str && !defaultString.isEmpty()) || needsTranslation(str)) return trCall(str, defaultString); return noTrCall(str, defaultString); } QTextStream &WriteInitialization::autoTrOutput(const DomProperty *property) { if (const DomString *str = property->elementString()) return autoTrOutput(str); if (const DomStringList *list = property->elementStringList()) if (needsTranslation(list)) return m_refreshOut; return m_output; } QTextStream &WriteInitialization::autoTrOutput(const DomString *str, const QString &defaultString) { if ((!str && !defaultString.isEmpty()) || needsTranslation(str)) return m_refreshOut; return m_output; } bool WriteInitialization::isValidObject(const QString &name) const { return m_registeredWidgets.contains(name) || m_registeredActions.contains(name); } QString WriteInitialization::findDeclaration(const QString &name) { const QString normalized = Driver::normalizedName(name); if (DomWidget *widget = m_driver->widgetByName(normalized)) return m_driver->findOrInsertWidget(widget); if (DomAction *action = m_driver->actionByName(normalized)) return m_driver->findOrInsertAction(action); if (const DomButtonGroup *group = m_driver->findButtonGroup(normalized)) return m_driver->findOrInsertButtonGroup(group); return QString(); } void WriteInitialization::acceptConnection(DomConnection *connection) { const QString sender = findDeclaration(connection->elementSender()); const QString receiver = findDeclaration(connection->elementReceiver()); if (sender.isEmpty() || receiver.isEmpty()) return; m_output << m_indent << "QObject::connect(" << sender << ", " << "SIGNAL("<elementSignal()<<')' << ", " << receiver << ", " << "SLOT("<elementSlot()<<')' << ");\n"; } DomWidget *WriteInitialization::findWidget(QLatin1String widgetClass) { for (int i = m_widgetChain.count() - 1; i >= 0; --i) { DomWidget *widget = m_widgetChain.at(i); if (widget && m_uic->customWidgetsInfo()->extends(widget->attributeClass(), widgetClass)) return widget; } return 0; } static void generateMultiDirectiveBegin(QTextStream &outputStream, const QSet &directives) { if (directives.isEmpty()) return; if (directives.size() == 1) { outputStream << "#ifndef " << *directives.cbegin() << endl; return; } auto list = directives.toList(); // sort (always generate in the same order): std::sort(list.begin(), list.end()); outputStream << "#if !defined(" << list.join(QLatin1String(") || !defined(")) << ')' << endl; } static void generateMultiDirectiveEnd(QTextStream &outputStream, const QSet &directives) { if (directives.isEmpty()) return; outputStream << "#endif" << endl; } WriteInitialization::Item::Item(const QString &itemClassName, const QString &indent, QTextStream &setupUiStream, QTextStream &retranslateUiStream, Driver *driver) : m_parent(0), m_itemClassName(itemClassName), m_indent(indent), m_setupUiStream(setupUiStream), m_retranslateUiStream(retranslateUiStream), m_driver(driver) { } WriteInitialization::Item::~Item() { qDeleteAll(m_children); } QString WriteInitialization::Item::writeSetupUi(const QString &parent, Item::EmptyItemPolicy emptyItemPolicy) { if (emptyItemPolicy == Item::DontConstruct && m_setupUiData.policy == ItemData::DontGenerate) return QString(); bool generateMultiDirective = false; if (emptyItemPolicy == Item::ConstructItemOnly && m_children.size() == 0) { if (m_setupUiData.policy == ItemData::DontGenerate) { m_setupUiStream << m_indent << "new " << m_itemClassName << '(' << parent << ");\n"; return QString(); } else if (m_setupUiData.policy == ItemData::GenerateWithMultiDirective) { generateMultiDirective = true; } } if (generateMultiDirective) generateMultiDirectiveBegin(m_setupUiStream, m_setupUiData.directives); const QString uniqueName = m_driver->unique(QLatin1String("__") + m_itemClassName.toLower()); m_setupUiStream << m_indent << m_itemClassName << " *" << uniqueName << " = new " << m_itemClassName << '(' << parent << ");\n"; if (generateMultiDirective) { m_setupUiStream << "#else\n"; m_setupUiStream << m_indent << "new " << m_itemClassName << '(' << parent << ");\n"; generateMultiDirectiveEnd(m_setupUiStream, m_setupUiData.directives); } QMultiMap::ConstIterator it = m_setupUiData.setters.constBegin(); while (it != m_setupUiData.setters.constEnd()) { openIfndef(m_setupUiStream, it.key()); m_setupUiStream << m_indent << uniqueName << it.value() << endl; closeIfndef(m_setupUiStream, it.key()); ++it; } for (Item *child : qAsConst(m_children)) child->writeSetupUi(uniqueName); return uniqueName; } void WriteInitialization::Item::writeRetranslateUi(const QString &parentPath) { if (m_retranslateUiData.policy == ItemData::DontGenerate) return; if (m_retranslateUiData.policy == ItemData::GenerateWithMultiDirective) generateMultiDirectiveBegin(m_retranslateUiStream, m_retranslateUiData.directives); const QString uniqueName = m_driver->unique(QLatin1String("___") + m_itemClassName.toLower()); m_retranslateUiStream << m_indent << m_itemClassName << " *" << uniqueName << " = " << parentPath << ";\n"; if (m_retranslateUiData.policy == ItemData::GenerateWithMultiDirective) generateMultiDirectiveEnd(m_retranslateUiStream, m_retranslateUiData.directives); QString oldDirective; QMultiMap::ConstIterator it = m_retranslateUiData.setters.constBegin(); while (it != m_retranslateUiData.setters.constEnd()) { const QString newDirective = it.key(); if (oldDirective != newDirective) { closeIfndef(m_retranslateUiStream, oldDirective); openIfndef(m_retranslateUiStream, newDirective); oldDirective = newDirective; } m_retranslateUiStream << m_indent << uniqueName << it.value() << endl; ++it; } closeIfndef(m_retranslateUiStream, oldDirective); for (int i = 0; i < m_children.size(); i++) m_children[i]->writeRetranslateUi(uniqueName + QLatin1String("->child(") + QString::number(i) + QLatin1Char(')')); } void WriteInitialization::Item::addSetter(const QString &setter, const QString &directive, bool translatable) { const ItemData::TemporaryVariableGeneratorPolicy newPolicy = directive.isNull() ? ItemData::Generate : ItemData::GenerateWithMultiDirective; if (translatable) { m_retranslateUiData.setters.insert(directive, setter); if (ItemData::GenerateWithMultiDirective == newPolicy) m_retranslateUiData.directives << directive; if (m_retranslateUiData.policy < newPolicy) m_retranslateUiData.policy = newPolicy; } else { m_setupUiData.setters.insert(directive, setter); if (ItemData::GenerateWithMultiDirective == newPolicy) m_setupUiData.directives << directive; if (m_setupUiData.policy < newPolicy) m_setupUiData.policy = newPolicy; } } void WriteInitialization::Item::addChild(Item *child) { m_children << child; child->m_parent = this; Item *c = child; Item *p = this; while (p) { p->m_setupUiData.directives |= c->m_setupUiData.directives; p->m_retranslateUiData.directives |= c->m_retranslateUiData.directives; if (p->m_setupUiData.policy < c->m_setupUiData.policy) p->m_setupUiData.policy = c->m_setupUiData.policy; if (p->m_retranslateUiData.policy < c->m_retranslateUiData.policy) p->m_retranslateUiData.policy = c->m_retranslateUiData.policy; c = p; p = p->m_parent; } } } // namespace CPP QT_END_NAMESPACE