diff options
Diffstat (limited to 'src/tools/uic')
25 files changed, 1477 insertions, 538 deletions
diff --git a/src/tools/uic/cpp/cppwriteincludes.cpp b/src/tools/uic/cpp/cppwriteincludes.cpp index 0ba49627c0..71e02ae9c9 100644 --- a/src/tools/uic/cpp/cppwriteincludes.cpp +++ b/src/tools/uic/cpp/cppwriteincludes.cpp @@ -69,7 +69,7 @@ static inline QString moduleHeader(const QString &module, const QString &header) namespace CPP { WriteIncludes::WriteIncludes(Uic *uic) - : m_uic(uic), m_output(uic->output()), m_laidOut(false) + : m_uic(uic), m_output(uic->output()) { // When possible (no namespace) use the "QtModule/QClass" convention // and create a re-mapping of the old header "qclass.h" to it. Do not do this diff --git a/src/tools/uic/cpp/cppwriteincludes.h b/src/tools/uic/cpp/cppwriteincludes.h index e9247f4cc4..9b9ac283fe 100644 --- a/src/tools/uic/cpp/cppwriteincludes.h +++ b/src/tools/uic/cpp/cppwriteincludes.h @@ -40,6 +40,7 @@ QT_BEGIN_NAMESPACE class QTextStream; +class CustomWidgetsInfo; class Driver; class Uic; @@ -74,11 +75,14 @@ struct WriteIncludes : public TreeWalker void acceptIncludes(DomIncludes *node) override; void acceptInclude(DomInclude *node) override; +protected: + QTextStream &output() const { return m_output; } + private: void add(const QString &className, bool determineHeader = true, const QString &header = QString(), bool global = false); private: - typedef std::set<QString> OrderedSet; + using OrderedSet = std::set<QString>; void insertIncludeForClass(const QString &className, QString header = QString(), bool global = false); void insertInclude(const QString &header, bool global); void writeHeaders(const OrderedSet &headers, bool global); @@ -93,11 +97,11 @@ private: QSet<QString> m_knownClasses; - typedef QMap<QString, QString> StringMap; + using StringMap = QMap<QString, QString>; StringMap m_classToHeader; StringMap m_oldHeaderToNewHeader; - bool m_laidOut; + bool m_laidOut = false; }; } // namespace CPP diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp index 2fb3e502c5..0349061089 100644 --- a/src/tools/uic/cpp/cppwriteinitialization.cpp +++ b/src/tools/uic/cpp/cppwriteinitialization.cpp @@ -71,7 +71,7 @@ namespace { // Write a statement to create a spacer item. void writeSpacerItem(const DomSpacer *node, QTextStream &output) { const QHash<QString, DomProperty *> properties = propertyMap(node->elementProperty()); - output << "new QSpacerItem("; + output << language::operatorNew << "QSpacerItem("; int w = 0; int h = 0; @@ -102,11 +102,9 @@ namespace { if (orientation == QLatin1String("Qt::Vertical") || orientation == QLatin1String("Vertical")) isVspacer = true; } - - if (isVspacer) - output << "QSizePolicy::Minimum, " << sizeType << ')'; - else - output << sizeType << ", QSizePolicy::Minimum)"; + const QString horizType = isVspacer ? QLatin1String("QSizePolicy::Minimum") : sizeType; + const QString vertType = isVspacer ? sizeType : QLatin1String("QSizePolicy::Minimum"); + output << language::enumValue(horizType) << ", " << language::enumValue(vertType) << ')'; } @@ -120,7 +118,8 @@ namespace { // Write object->setFoo(x); template <class Value> void writeSetter(const QString &indent, const QString &varName,const QString &setter, Value v, QTextStream &str) { - str << indent << varName << "->" << setter << '(' << v << ");\n"; + str << indent << varName << language::derefPointer + << setter << '(' << v << ')' << language::eol; } static inline bool iconHasStatePixmaps(const DomResourceIcon *i) { @@ -456,22 +455,20 @@ WriteInitialization::WriteInitialization(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) + m_actionOut(&m_delayedActionInitialization, QIODevice::WriteOnly) { } void WriteInitialization::acceptUI(DomUI *node) { - m_actionGroupChain.push(0); - m_widgetChain.push(0); - m_layoutChain.push(0); + m_actionGroupChain.push(nullptr); + m_widgetChain.push(nullptr); + m_layoutChain.push(nullptr); + + if (node->hasAttributeConnectslotsbyname()) + m_connectSlotsByName = node->attributeConnectslotsbyname(); acceptLayoutDefault(node->elementLayoutDefault()); acceptLayoutFunction(node->elementLayoutFunction()); @@ -491,22 +488,21 @@ void WriteInitialization::acceptUI(DomUI *node) 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 QString parameterType = widgetClassName + QLatin1String(" *"); + m_output << m_option.indent + << language::startFunctionDefinition1("setupUi", parameterType, varName, m_option.indent); const QStringList connections = m_uic->databaseInfo()->connections(); - for (int i=0; i<connections.size(); ++i) { - QString connection = connections.at(i); - + for (const auto &connection : connections) { if (connection == QLatin1String("(default)")) continue; const QString varConn = connection + QLatin1String("Connection"); - m_output << m_indent << varConn << " = QSqlDatabase::database(" << fixString(connection, m_dindent) << ");\n"; + m_output << m_indent << varConn << " = QSqlDatabase::database(" + << language::charliteral(connection, m_dindent) << ")" << language::eol; } acceptWidget(node->elementWidget()); @@ -514,20 +510,16 @@ void WriteInitialization::acceptUI(DomUI *node) if (!m_buddies.empty()) m_output << language::openQtConfig(shortcutConfigKey()); for (const Buddy &b : qAsConst(m_buddies)) { - if (!m_registeredWidgets.contains(b.objName)) { + const QString buddyVarName = m_driver->widgetVariableName(b.buddyAttributeName); + if (buddyVarName.isEmpty()) { fprintf(stderr, "%s: Warning: Buddy assignment: '%s' is not a valid widget.\n", qPrintable(m_option.messagePrefix()), - b.objName.toLatin1().data()); - continue; - } - if (!m_registeredWidgets.contains(b.buddy)) { - fprintf(stderr, "%s: Warning: Buddy assignment: '%s' is not a valid widget.\n", - qPrintable(m_option.messagePrefix()), - b.buddy.toLatin1().data()); + qPrintable(b.buddyAttributeName)); continue; } - m_output << m_indent << b.objName << "->setBuddy(" << b.buddy << ");\n"; + m_output << m_indent << b.labelVarName << language::derefPointer + << "setBuddy(" << buddyVarName << ')' << language::eol; } if (!m_buddies.empty()) m_output << language::closeQtConfig(shortcutConfigKey()); @@ -538,7 +530,8 @@ void WriteInitialization::acceptUI(DomUI *node) if (!m_delayedActionInitialization.isEmpty()) m_output << "\n" << m_delayedActionInitialization; - m_output << "\n" << m_indent << "retranslateUi(" << varName << ");\n"; + m_output << "\n" << m_indent << language::self + << "retranslateUi(" << varName << ')' << language::eol; if (node->elementConnections()) acceptConnections(node->elementConnections()); @@ -546,22 +539,25 @@ void WriteInitialization::acceptUI(DomUI *node) if (!m_delayedInitialization.isEmpty()) m_output << "\n" << m_delayedInitialization << "\n"; - if (m_option.autoConnection) - m_output << "\n" << m_indent << "QMetaObject::connectSlotsByName(" << varName << ");\n"; + if (m_option.autoConnection && m_connectSlotsByName) { + m_output << "\n" << m_indent << "QMetaObject" << language::qualifier + << "connectSlotsByName(" << varName << ')' << language::eol; + } - m_output << m_option.indent << "} // setupUi\n\n"; + m_output << m_option.indent << language::endFunctionDefinition("setupUi"); - if (!m_mainFormUsedInRetranslateUi) { + if (!m_mainFormUsedInRetranslateUi && language::language() == Language::Cpp) { + // Mark varName as unused to avoid compiler warnings. m_refreshInitialization += m_indent; - m_refreshInitialization += QLatin1String("Q_UNUSED("); + m_refreshInitialization += QLatin1String("(void)"); m_refreshInitialization += varName ; - m_refreshInitialization += QLatin1String(");\n"); + m_refreshInitialization += language::eol; } - m_output << m_option.indent << "void " << "retranslateUi(" << widgetClassName << " *" << varName << ")\n" - << m_option.indent << "{\n" + m_output << m_option.indent + << language::startFunctionDefinition1("retranslateUi", parameterType, varName, m_option.indent) << m_refreshInitialization - << m_option.indent << "} // retranslateUi\n\n"; + << m_option.indent << language::endFunctionDefinition("retranslateUi"); m_layoutChain.pop(); m_widgetChain.pop(); @@ -584,9 +580,11 @@ void WriteInitialization::addWizardPage(const QString &pageVarName, const DomWid } } if (id.isEmpty()) { - m_output << m_indent << parentWidget << "->addPage(" << pageVarName << ");\n"; + m_output << m_indent << parentWidget << language::derefPointer + << "addPage(" << pageVarName << ')' << language::eol; } else { - m_output << m_indent << parentWidget << "->setPage(" << id << ", " << pageVarName << ");\n"; + m_output << m_indent << parentWidget << language::derefPointer + << "setPage(" << id << ", " << pageVarName << ')' << language::eol; } } @@ -595,7 +593,6 @@ 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()) { @@ -611,8 +608,9 @@ void WriteInitialization::acceptWidget(DomWidget *node) const auto *cwi = m_uic->customWidgetsInfo(); if (m_widgetChain.size() != 1) { - m_output << m_indent << varName << " = new " << cwi->realClassName(className) - << '(' << parentWidget << ");\n"; + m_output << m_indent << varName << " = " << language::operatorNew + << language::fixClassName(cwi->realClassName(className)) + << '(' << parentWidget << ')' << language::eol; } parentWidget = savedParentWidget; @@ -664,26 +662,33 @@ void WriteInitialization::acceptWidget(DomWidget *node) if (cwi->extends(parentClass, QLatin1String("QMainWindow"))) { if (cwi->extends(className, QLatin1String("QMenuBar"))) { - m_output << m_indent << parentWidget << "->setMenuBar(" << varName <<");\n"; + m_output << m_indent << parentWidget << language::derefPointer + << "setMenuBar(" << varName << ')' << language::eol; } else if (cwi->extends(className, QLatin1String("QToolBar"))) { - m_output << m_indent << parentWidget << "->addToolBar(" - << toolBarAreaStringFromDOMAttributes(attributes) << varName << ");\n"; + m_output << m_indent << parentWidget << language::derefPointer << "addToolBar(" + << language::enumValue(toolBarAreaStringFromDOMAttributes(attributes)) << varName + << ')' << language::eol; if (const DomProperty *pbreak = attributes.value(QLatin1String("toolBarBreak"))) { if (pbreak->elementBool() == QLatin1String("true")) { - m_output << m_indent << parentWidget << "->insertToolBarBreak(" << varName << ");\n"; + m_output << m_indent << parentWidget << language::derefPointer + << "insertToolBarBreak(" << varName << ')' << language::eol; } } } else if (cwi->extends(className, QLatin1String("QDockWidget"))) { - m_output << m_indent << parentWidget << "->addDockWidget("; - if (DomProperty *pstyle = attributes.value(QLatin1String("dockWidgetArea"))) - m_output << "Qt::" << language::dockWidgetArea(pstyle->elementNumber()) << ", "; - m_output << varName << ");\n"; + m_output << m_indent << parentWidget << language::derefPointer << "addDockWidget("; + if (DomProperty *pstyle = attributes.value(QLatin1String("dockWidgetArea"))) { + m_output << "Qt" << language::qualifier + << language::dockWidgetArea(pstyle->elementNumber()) << ", "; + } + m_output << varName << ")" << language::eol; } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QStatusBar"))) { - m_output << m_indent << parentWidget << "->setStatusBar(" << varName << ");\n"; + m_output << m_indent << parentWidget << language::derefPointer + << "setStatusBar(" << varName << ')' << language::eol; } else { - m_output << m_indent << parentWidget << "->setCentralWidget(" << varName << ");\n"; + m_output << m_indent << parentWidget << language::derefPointer + << "setCentralWidget(" << varName << ')' << language::eol; } } @@ -692,56 +697,61 @@ void WriteInitialization::acceptWidget(DomWidget *node) if (addPageMethod.isEmpty()) addPageMethod = cwi->simpleContainerAddPageMethod(parentClass); if (!addPageMethod.isEmpty()) { - m_output << m_indent << parentWidget << "->" << addPageMethod << '(' << varName << ");\n"; + m_output << m_indent << parentWidget << language::derefPointer + << addPageMethod << '(' << varName << ')' << language::eol; } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QWizard"))) { addWizardPage(varName, node, parentWidget); } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QToolBox"))) { const DomProperty *plabel = attributes.value(QLatin1String("label")); - DomString *plabelString = plabel ? plabel->elementString() : 0; + DomString *plabelString = plabel ? plabel->elementString() : nullptr; QString icon; if (const DomProperty *picon = attributes.value(QLatin1String("icon"))) icon = QLatin1String(", ") + iconCall(picon); // Side effect: Writes icon definition + m_output << m_indent << parentWidget << language::derefPointer << "addItem(" + << varName << icon << ", " << noTrCall(plabelString, pageDefaultString) + << ')' << language::eol; - 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"; + autoTrOutput(plabelString, pageDefaultString) << m_indent << parentWidget + << language::derefPointer << "setItemText(" << parentWidget + << language::derefPointer << "indexOf(" << varName << "), " + << autoTrCall(plabelString, pageDefaultString) << ')' << language::eol; if (DomProperty *ptoolTip = attributes.value(QLatin1String("toolTip"))) { autoTrOutput(ptoolTip->elementString()) << language::openQtConfig(toolTipConfigKey()) - << m_indent << parentWidget << "->setItemToolTip(" << parentWidget - << "->indexOf(" << varName << "), " - << autoTrCall(ptoolTip->elementString()) << ");\n" + << m_indent << parentWidget << language::derefPointer << "setItemToolTip(" << parentWidget + << language::derefPointer << "indexOf(" << varName << "), " + << autoTrCall(ptoolTip->elementString()) << ')' << language::eol << language::closeQtConfig(toolTipConfigKey()); } } else if (m_uic->customWidgetsInfo()->extends(parentClass, QLatin1String("QTabWidget"))) { const DomProperty *ptitle = attributes.value(QLatin1String("title")); - DomString *ptitleString = ptitle ? ptitle->elementString() : 0; + DomString *ptitleString = ptitle ? ptitle->elementString() : nullptr; QString icon; if (const DomProperty *picon = attributes.value(QLatin1String("icon"))) icon = QLatin1String(", ") + iconCall(picon); // Side effect: Writes icon definition - m_output << m_indent << parentWidget << "->addTab(" << varName << icon - << ", " << "QString());\n"; + m_output << m_indent << parentWidget << language::derefPointer << "addTab(" + << varName << icon << ", " << "QString())" << language::eol; - autoTrOutput(ptitleString, pageDefaultString) << m_indent << parentWidget << "->setTabText(" - << parentWidget << "->indexOf(" << varName << "), " << autoTrCall(ptitleString, pageDefaultString) << ");\n"; + autoTrOutput(ptitleString, pageDefaultString) << m_indent << parentWidget + << language::derefPointer << "setTabText(" << parentWidget + << language::derefPointer << "indexOf(" << varName << "), " + << autoTrCall(ptitleString, pageDefaultString) << ')' << language::eol; if (const DomProperty *ptoolTip = attributes.value(QLatin1String("toolTip"))) { autoTrOutput(ptoolTip->elementString()) << language::openQtConfig(toolTipConfigKey()) - << m_indent << parentWidget << "->setTabToolTip(" << parentWidget - << "->indexOf(" << varName << "), " - << autoTrCall(ptoolTip->elementString()) << ");\n" + << m_indent << parentWidget << language::derefPointer << "setTabToolTip(" + << parentWidget << language::derefPointer << "indexOf(" << varName + << "), " << autoTrCall(ptoolTip->elementString()) << ')' << language::eol << language::closeQtConfig(toolTipConfigKey()); } if (const DomProperty *pwhatsThis = attributes.value(QLatin1String("whatsThis"))) { autoTrOutput(pwhatsThis->elementString()) << language::openQtConfig(whatsThisConfigKey()) - << m_indent << parentWidget << "->setTabWhatsThis(" << parentWidget - << "->indexOf(" << varName << "), " - << autoTrCall(pwhatsThis->elementString()) << ");\n" + << m_indent << parentWidget << language::derefPointer << "setTabWhatsThis(" + << parentWidget << language::derefPointer << "indexOf(" << varName + << "), " << autoTrCall(pwhatsThis->elementString()) << ')' << language::eol << language::closeQtConfig(whatsThisConfigKey()); } } @@ -776,8 +786,9 @@ void WriteInitialization::acceptWidget(DomWidget *node) headerProperties << fakeProperty; } } - writeProperties(varName + QLatin1String("->header()"), QLatin1String("QHeaderView"), - headerProperties, WritePropertyIgnoreObjectName); + writeProperties(varName + language::derefPointer + QLatin1String("header()"), + QLatin1String("QHeaderView"), headerProperties, + WritePropertyIgnoreObjectName); } else if (cwi->extendsOneOf(className, tables)) { static const QLatin1String headerPrefixes[] = { @@ -795,8 +806,9 @@ void WriteInitialization::acceptWidget(DomWidget *node) headerProperties << fakeProperty; } } - writeProperties(varName + QLatin1String("->") + headerPrefix + QLatin1String("()"), - QLatin1String("QHeaderView"), + const QString headerVar = varName + language::derefPointer + + headerPrefix + QLatin1String("()"); + writeProperties(headerVar, QLatin1String("QHeaderView"), headerProperties, WritePropertyIgnoreObjectName); } } @@ -806,15 +818,15 @@ void WriteInitialization::acceptWidget(DomWidget *node) const QStringList zOrder = node->elementZOrder(); for (const QString &name : zOrder) { - if (!m_registeredWidgets.contains(name)) { + const QString varName = m_driver->widgetVariableName(name); + if (varName.isEmpty()) { fprintf(stderr, "%s: Warning: Z-order assignment: '%s' is not a valid widget.\n", qPrintable(m_option.messagePrefix()), name.toLatin1().data()); - continue; + } else { + m_output << m_indent << varName << language::derefPointer << "raise()" + << language::eol; } - - if (!name.isEmpty()) - m_output << m_indent << name << "->raise();\n"; } } @@ -829,7 +841,7 @@ void WriteInitialization::addButtonGroup(const DomWidget *buttonNode, const QStr 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; + const bool createGroupOnTheFly = group == nullptr; if (createGroupOnTheFly) { DomButtonGroup *newGroup = new DomButtonGroup; newGroup->setAttributeName(attributeName); @@ -845,11 +857,13 @@ void WriteInitialization::addButtonGroup(const DomWidget *buttonNode, const QStr m_output << m_indent; if (createGroupOnTheFly) m_output << className << " *"; - m_output << groupName << " = new " << className << '(' << m_mainFormVarName << ");\n"; + m_output << groupName << " = " << language::operatorNew + << className << '(' << m_mainFormVarName << ')' << language::eol; m_buttonGroups.insert(groupName); writeProperties(groupName, className, group->elementProperty()); } - m_output << m_indent << groupName << "->addButton(" << varName << ");\n"; + m_output << m_indent << groupName << language::derefPointer << "addButton(" + << varName << ')' << language::eol; } void WriteInitialization::acceptLayout(DomLayout *node) @@ -862,12 +876,12 @@ void WriteInitialization::acceptLayout(DomLayout *node) bool isGroupBox = false; - m_output << m_indent << varName << " = new " << className << '('; + m_output << m_indent << varName << " = " << language::operatorNew << className << '('; if (!m_layoutChain.top() && !isGroupBox) m_output << m_driver->findOrInsertWidget(m_widgetChain.top()); - m_output << ");\n"; + m_output << ")" << language::eol; // Suppress margin on a read child layout const bool suppressMarginDefault = m_layoutChain.top(); @@ -883,8 +897,7 @@ void WriteInitialization::acceptLayout(DomLayout *node) 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); + for (const DomProperty *p : propList) { const QString propertyName = p->attributeName(); if (propertyName == QLatin1String("leftMargin") && p->kind() == DomProperty::Number) left = true; @@ -954,16 +967,19 @@ void WriteInitialization::writePropertyList(const QString &varName, 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"; + for (int i = 0; i < count; i++) { + if (list.at(i) != defaultValue) { + m_output << m_indent << varName << language::derefPointer << setFunction + << '(' << i << ", " << list.at(i) << ')' << language::eol; + } + } } void WriteInitialization::acceptSpacer(DomSpacer *node) { m_output << m_indent << m_driver->findOrInsertSpacer(node) << " = "; writeSpacerItem(node, m_output); - m_output << ";\n"; + m_output << language::eol; } static inline QString formLayoutRole(int column, int colspan) @@ -1003,7 +1019,7 @@ void WriteInitialization::acceptLayoutItem(DomLayoutItem *node) const QString layoutName = m_driver->findOrInsertLayout(layout); const QString itemName = m_driver->findOrInsertLayoutItem(node); - m_output << "\n" << m_indent << layoutName << "->" + m_output << "\n" << m_indent << layoutName << language::derefPointer << "" << layoutAddMethod(node->kind(), layout->attributeClass()) << '('; if (layout->attributeClass() == QLatin1String("QGridLayout")) { @@ -1014,18 +1030,18 @@ void WriteInitialization::acceptLayoutItem(DomLayoutItem *node) const int colSpan = node->hasAttributeColSpan() ? node->attributeColSpan() : 1; m_output << itemName << ", " << row << ", " << col << ", " << rowSpan << ", " << colSpan; if (!node->attributeAlignment().isEmpty()) - m_output << ", " << node->attributeAlignment(); + m_output << ", " << language::enumValue(node->attributeAlignment()); } else if (layout->attributeClass() == QLatin1String("QFormLayout")) { const int row = node->attributeRow(); const int colSpan = node->hasAttributeColSpan() ? node->attributeColSpan() : 1; const QString role = formLayoutRole(node->attributeColumn(), colSpan); - m_output << row << ", " << role << ", " << itemName; + m_output << row << ", " << language::enumValue(role) << ", " << itemName; } else { m_output << itemName; if (layout->attributeClass().contains(QLatin1String("Box")) && !node->attributeAlignment().isEmpty()) - m_output << ", 0, " << node->attributeAlignment(); + m_output << ", 0, " << language::enumValue(node->attributeAlignment()); } - m_output << ");\n\n"; + m_output << ")" << language::eol << "\n"; } void WriteInitialization::acceptActionGroup(DomActionGroup *node) @@ -1036,7 +1052,8 @@ void WriteInitialization::acceptActionGroup(DomActionGroup *node) if (m_actionGroupChain.top()) varName = m_driver->findOrInsertActionGroup(m_actionGroupChain.top()); - m_output << m_indent << actionName << " = new QActionGroup(" << varName << ");\n"; + m_output << m_indent << actionName << " = " << language::operatorNew + << "QActionGroup(" << varName << ")" << language::eol; writeProperties(actionName, QLatin1String("QActionGroup"), node->elementProperty()); m_actionGroupChain.push(node); @@ -1050,13 +1067,13 @@ void WriteInitialization::acceptAction(DomAction *node) 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"; + m_output << m_indent << actionName << " = " << language::operatorNew + << "QAction(" << varName << ')' << language::eol; writeProperties(actionName, QLatin1String("QAction"), node->elementProperty()); } @@ -1069,28 +1086,32 @@ void WriteInitialization::acceptActionRef(DomActionRef *node) } const QString varName = m_driver->findOrInsertWidget(m_widgetChain.top()); - const bool isSeparator = actionName == QLatin1String("separator"); - bool isMenu = false; - 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()); + if (m_widgetChain.top() && actionName == QLatin1String("separator")) { + // separator is always reserved! + m_actionOut << m_indent << varName << language::derefPointer + << "addSeparator()" << language::eol; return; } - if (m_widgetChain.top() && isSeparator) { - // separator is always reserved! - m_actionOut << m_indent << varName << "->addSeparator();\n"; + const DomWidget *domWidget = m_driver->widgetByName(actionName); + if (domWidget && m_uic->isMenu(domWidget->attributeClass())) { + m_actionOut << m_indent << varName << language::derefPointer + << "addAction(" << m_driver->findOrInsertWidget(domWidget) + << language::derefPointer << "menuAction())" << language::eol; return; } - if (isMenu) - actionName += QLatin1String("->menuAction()"); + const DomAction *domAction = m_driver->actionByName(actionName); + if (!domAction) { + fprintf(stderr, "%s: Warning: action `%s' not declared\n", + qPrintable(m_option.messagePrefix()), qPrintable(actionName)); + return; + } - m_actionOut << m_indent << varName << "->addAction(" << actionName << ");\n"; + m_actionOut << m_indent << varName << language::derefPointer + << "addAction(" << m_driver->findOrInsertAction(domAction) + << ')' << language::eol; } QString WriteInitialization::writeStringListProperty(const DomStringList *list) const @@ -1107,7 +1128,7 @@ QString WriteInitialization::writeStringListProperty(const DomStringList *list) str << '\n' << m_indent << " << " << trCall(values.at(i), comment); } else { for (int i = 0; i < values.size(); ++i) - str << " << QString::fromUtf8(" << fixString(values.at(i), m_dindent) << ')'; + str << " << " << language::qstring(values.at(i), m_dindent); } return propertyValue; } @@ -1139,19 +1160,32 @@ void WriteInitialization::writeProperties(const QString &varName, 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(QString::fromUtf8(" - << fixString(toString(p->elementString()), m_dindent) << "));\n"; + m_output << m_indent << varName << language::derefPointer << "setControl(" + << language::qstring(toString(p->elementString()), m_dindent) + << ')' << language::eol; } } QString indent; if (!m_widgetChain.top()) { indent = m_option.indent; - m_output << m_indent << "if (" << varName << "->objectName().isEmpty())\n"; + switch (language::language()) { + case Language::Cpp: + m_output << m_indent << "if (" << varName << "->objectName().isEmpty())\n"; + break; + case Language::Python: + m_output << m_indent << "if " << varName << ".objectName():\n"; + break; + } + } + if (!(flags & WritePropertyIgnoreObjectName)) { + QString objectName = varName; + if (!language::self.isEmpty() && objectName.startsWith(language::self)) + objectName.remove(0, language::self.size()); + m_output << m_indent << indent + << varName << language::derefPointer << "setObjectName(" + << language::qstring(objectName, m_dindent) << ')' << language::eol; } - if (!(flags & WritePropertyIgnoreObjectName)) - m_output << m_indent << indent << varName - << "->setObjectName(QString::fromUtf8(" << fixString(varName, m_dindent) << "));\n"; int leftMargin, topMargin, rightMargin, bottomMargin; leftMargin = topMargin = rightMargin = bottomMargin = -1; @@ -1167,13 +1201,14 @@ void WriteInitialization::writeProperties(const QString &varName, // 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"; + m_output << m_indent << varName << language::derefPointer << "resize(" + << r->elementWidth() << ", " << r->elementHeight() << ')' << language::eol; continue; } if (propertyName == QLatin1String("currentRow") // QListWidget::currentRow && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QListWidget"))) { - m_delayedOut << m_indent << varName << "->setCurrentRow(" - << p->elementNumber() << ");\n"; + m_delayedOut << m_indent << varName << language::derefPointer + << "setCurrentRow(" << p->elementNumber() << ')' << language::eol; continue; } static const QStringList currentIndexWidgets = { @@ -1182,14 +1217,15 @@ void WriteInitialization::writeProperties(const QString &varName, }; if (propertyName == QLatin1String("currentIndex") // set currentIndex later && (m_uic->customWidgetsInfo()->extendsOneOf(className, currentIndexWidgets))) { - m_delayedOut << m_indent << varName << "->setCurrentIndex(" - << p->elementNumber() << ");\n"; + m_delayedOut << m_indent << varName << language::derefPointer + << "setCurrentIndex(" << p->elementNumber() << ')' << language::eol; continue; } if (propertyName == QLatin1String("tabSpacing") && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QToolBox"))) { - m_delayedOut << m_indent << varName << "->layout()->setSpacing(" - << p->elementNumber() << ");\n"; + m_delayedOut << m_indent << varName << language::derefPointer + << "layout()" << language::derefPointer << "setSpacing(" + << p->elementNumber() << ')' << language::eol; continue; } if (propertyName == QLatin1String("control") // ActiveQt support @@ -1216,10 +1252,15 @@ void WriteInitialization::writeProperties(const QString &varName, if (p->elementEnum() == QLatin1String("Qt::Vertical")) shape = QLatin1String("QFrame::VLine"); - m_output << m_indent << varName << "->setFrameShape(" << shape << ");\n"; + m_output << m_indent << varName << language::derefPointer << "setFrameShape(" + << language::enumValue(shape) << ')' << language::eol; // QFrame Default is 'Plain'. Make the line 'Sunken' unless otherwise specified - if (!frameShadowEncountered) - m_output << m_indent << varName << "->setFrameShadow(QFrame::Sunken);\n"; + if (!frameShadowEncountered) { + m_output << m_indent << varName << language::derefPointer + << "setFrameShadow(" + << language::enumValue(QLatin1String("QFrame::Sunken")) + << ')' << language::eol; + } continue; } else if ((flags & WritePropertyIgnoreMargin) && propertyName == QLatin1String("margin")) { continue; @@ -1251,25 +1292,28 @@ void WriteInitialization::writeProperties(const QString &varName, QString setFunction; - if (stdset) { - setFunction = QLatin1String("->set") - + propertyName.at(0).toUpper() - + propertyName.midRef(1) - + QLatin1Char('('); - } else { - setFunction += QLatin1String("->setProperty(\"") - + propertyName - + QLatin1String("\", QVariant"); - if (p->kind() == DomProperty::Enum) - setFunction += QLatin1String("::fromValue"); - setFunction += QLatin1Char('('); - } + { + QTextStream str(&setFunction); + if (stdset) { + str << language::derefPointer <<"set" << propertyName.at(0).toUpper() + << propertyName.midRef(1) << '('; + } else { + str << language::derefPointer << QLatin1String("setProperty(\"") + << propertyName << "\", "; + if (language::language() == Language::Cpp) { + str << "QVariant"; + if (p->kind() == DomProperty::Enum) + str << "::fromValue"; + str << '('; + } + } + } // QTextStream QString varNewName = varName; switch (p->kind()) { case DomProperty::Bool: { - propertyValue = p->elementBool(); + propertyValue = language::boolValue(p->elementBool() == language::cppTrue); break; } case DomProperty::Color: @@ -1280,13 +1324,12 @@ void WriteInitialization::writeProperties(const QString &varName, 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(')'); - } + QTextStream str(&propertyValue); + if (!stdset) + str << "QByteArray("; + str << language::charliteral(p->elementCstring(), m_dindent); + if (!stdset) + str << ')'; } break; case DomProperty::Cursor: @@ -1295,17 +1338,19 @@ void WriteInitialization::writeProperties(const QString &varName, break; case DomProperty::CursorShape: if (p->hasAttributeStdset() && !p->attributeStdset()) - varNewName += QLatin1String("->viewport()"); - propertyValue = QString::fromLatin1("QCursor(Qt::%1)") - .arg(p->elementCursorShape()); + varNewName += language::derefPointer + QLatin1String("viewport()"); + propertyValue = QLatin1String("QCursor(Qt") + language::qualifier + + p->elementCursorShape() + QLatin1Char(')'); break; case DomProperty::Enum: propertyValue = p->elementEnum(); - if (!propertyValue.contains(QLatin1String("::"))) - propertyValue = className + QLatin1String("::") + propertyValue; + if (propertyValue.contains(language::cppQualifier)) + propertyValue = language::enumValue(propertyValue); + else + propertyValue.prepend(className + language::qualifier); break; case DomProperty::Set: - propertyValue = p->elementSet(); + propertyValue = language::enumValue(p->elementSet()); break; case DomProperty::Font: propertyValue = writeFontProperties(p->elementFont()); @@ -1319,8 +1364,8 @@ void WriteInitialization::writeProperties(const QString &varName, case DomProperty::Palette: { const DomPalette *pal = p->elementPalette(); const QString paletteName = m_driver->unique(QLatin1String("palette")); - m_output << m_indent << "QPalette " << paletteName << ";\n"; - + m_output << m_indent << language::stackVariable("QPalette", paletteName) + << language::eol; writeColorGroup(pal->elementActive(), QLatin1String("QPalette::Active"), paletteName); writeColorGroup(pal->elementInactive(), QLatin1String("QPalette::Inactive"), paletteName); writeColorGroup(pal->elementDisabled(), QLatin1String("QPalette::Disabled"), paletteName); @@ -1356,15 +1401,16 @@ void WriteInitialization::writeProperties(const QString &varName, } case DomProperty::Locale: { const DomLocale *locale = p->elementLocale(); - propertyValue = QString::fromLatin1("QLocale(QLocale::%1, QLocale::%2)") - .arg(locale->attributeLanguage(), locale->attributeCountry()); + QTextStream(&propertyValue) << "QLocale(QLocale" << language::qualifier + << locale->attributeLanguage() << ", QLocale" << language::qualifier + << 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); + m_output << m_indent << spName << ".setHeightForWidth(" + << varName << language::derefPointer << "sizePolicy().hasHeightForWidth())" + << language::eol; propertyValue = spName; break; @@ -1455,8 +1501,8 @@ void WriteInitialization::writeProperties(const QString &varName, case DomProperty::Url: { const DomUrl* u = p->elementUrl(); - propertyValue = QString::fromLatin1("QUrl(QString::fromUtf8(%1))") - .arg(fixString(u->elementString()->text(), m_dindent)); + QTextStream(&propertyValue) << "QUrl(" + << language::qstring(u->elementString()->text(), m_dindent) << ")"; break; } case DomProperty::Brush: @@ -1474,9 +1520,9 @@ void WriteInitialization::writeProperties(const QString &varName, if (!configKey.isEmpty()) o << language::openQtConfig(configKey); o << m_indent << varNewName << setFunction << propertyValue; - if (!stdset) + if (!stdset && language::language() == Language::Cpp) o << ')'; - o << ");\n"; + o << ')' << language::eol; if (!configKey.isEmpty()) o << language::closeQtConfig(configKey); @@ -1488,9 +1534,9 @@ void WriteInitialization::writeProperties(const QString &varName, } } if (leftMargin != -1 || topMargin != -1 || rightMargin != -1 || bottomMargin != -1) { - m_output << m_indent << varName << "->setContentsMargins(" + m_output << m_indent << varName << language::derefPointer << "setContentsMargins(" << leftMargin << ", " << topMargin << ", " - << rightMargin << ", " << bottomMargin << ");\n"; + << rightMargin << ", " << bottomMargin << ")" << language::eol; } } @@ -1509,25 +1555,20 @@ QString WriteInitialization::writeSizePolicy(const DomSizePolicy *sp) 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 << "(QSizePolicy::" << language::sizePolicy(sp->elementHSizeType()) - << ", QSizePolicy::" << language::sizePolicy(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 << language::stackVariableWithInitParameters("QSizePolicy", spName); + if (sp->hasElementHSizeType() && sp->hasElementVSizeType()) { + m_output << "QSizePolicy" << language::qualifier << language::sizePolicy(sp->elementHSizeType()) + << ", QSizePolicy" << language::qualifier << language::sizePolicy(sp->elementVSizeType()); + } else if (sp->hasAttributeHSizeType() && sp->hasAttributeVSizeType()) { + m_output << "QSizePolicy" << language::qualifier << sp->attributeHSizeType() + << ", QSizePolicy" << language::qualifier << sp->attributeVSizeType(); + } + m_output << ')' << language::eol; m_output << m_indent << spName << ".setHorizontalStretch(" - << sp->elementHorStretch() << ");\n"; + << sp->elementHorStretch() << ")" << language::eol; m_output << m_indent << spName << ".setVerticalStretch(" - << sp->elementVerStretch() << ");\n"; + << sp->elementVerStretch() << ")" << language::eol; return spName; } // Check for a font with the given properties in the FontPropertiesNameMap @@ -1546,51 +1587,64 @@ QString WriteInitialization::writeFontProperties(const DomFont *f) const QString fontName = m_driver->unique(QLatin1String("font")); m_fontPropertiesNameMap.insert(FontHandle(f), fontName); - m_output << m_indent << "QFont " << fontName << ";\n"; + m_output << m_indent << language::stackVariable("QFont", fontName) + << language::eol; if (f->hasElementFamily() && !f->elementFamily().isEmpty()) { - m_output << m_indent << fontName << ".setFamily(QString::fromUtf8(" - << fixString(f->elementFamily(), m_dindent) << "));\n"; + m_output << m_indent << fontName << ".setFamily(" + << language::qstring(f->elementFamily(), m_dindent) << ")" << language::eol; } if (f->hasElementPointSize() && f->elementPointSize() > 0) { m_output << m_indent << fontName << ".setPointSize(" << f->elementPointSize() - << ");\n"; + << ")" << language::eol; } if (f->hasElementBold()) { m_output << m_indent << fontName << ".setBold(" - << (f->elementBold() ? "true" : "false") << ");\n"; + << language::boolValue(f->elementBold()) << ')' << language::eol; } if (f->hasElementItalic()) { m_output << m_indent << fontName << ".setItalic(" - << (f->elementItalic() ? "true" : "false") << ");\n"; + << language::boolValue(f->elementItalic()) << ')' << language::eol; } if (f->hasElementUnderline()) { m_output << m_indent << fontName << ".setUnderline(" - << (f->elementUnderline() ? "true" : "false") << ");\n"; + << language::boolValue(f->elementUnderline()) << ')' << language::eol; } if (f->hasElementWeight() && f->elementWeight() > 0) { m_output << m_indent << fontName << ".setWeight(" - << f->elementWeight() << ");" << endl; + << f->elementWeight() << ");" << Qt::endl; } if (f->hasElementStrikeOut()) { m_output << m_indent << fontName << ".setStrikeOut(" - << (f->elementStrikeOut() ? "true" : "false") << ");\n"; + << language::boolValue(f->elementStrikeOut()) << ')' << language::eol; } if (f->hasElementKerning()) { m_output << m_indent << fontName << ".setKerning(" - << (f->elementKerning() ? "true" : "false") << ");\n"; + << language::boolValue(f->elementKerning()) << ')' << language::eol; } if (f->hasElementAntialiasing()) { - m_output << m_indent << fontName << ".setStyleStrategy(" - << (f->elementAntialiasing() ? "QFont::PreferDefault" : "QFont::NoAntialias") << ");\n"; + m_output << m_indent << fontName << ".setStyleStrategy(QFont" + << language::qualifier + << (f->elementAntialiasing() ? "PreferDefault" : "NoAntialias") + << ')' << language::eol; } if (f->hasElementStyleStrategy()) { - m_output << m_indent << fontName << ".setStyleStrategy(QFont::" - << f->elementStyleStrategy() << ");\n"; + m_output << m_indent << fontName << ".setStyleStrategy(QFont" + << language::qualifier << f->elementStyleStrategy() << ')' << language::eol; } return fontName; } +static void writeIconAddFile(QTextStream &output, const QString &indent, + const QString &iconName, const QString &fileName, + const char *mode, const char *state) +{ + output << indent << iconName << ".addFile(" + << language::qstring(fileName, indent) << ", QSize(), QIcon" + << language::qualifier << mode << ", QIcon" << language::qualifier + << state << ')' << language::eol; +} + // Post 4.4 write resource icon static void writeResourceIcon(QTextStream &output, const QString &iconName, @@ -1598,91 +1652,92 @@ static void writeResourceIcon(QTextStream &output, const DomResourceIcon *i) { if (i->hasElementNormalOff()) { - output << indent << iconName << ".addFile(QString::fromUtf8(" - << fixString(i->elementNormalOff()->text(), indent) - << "), QSize(), QIcon::Normal, QIcon::Off);\n"; + writeIconAddFile(output, indent, iconName, i->elementNormalOff()->text(), + "Normal", "Off"); } if (i->hasElementNormalOn()) { - output << indent << iconName << ".addFile(QString::fromUtf8(" - << fixString(i->elementNormalOn()->text(), indent) - << "), QSize(), QIcon::Normal, QIcon::On);\n"; + writeIconAddFile(output, indent, iconName, i->elementNormalOn()->text(), + "Normal", "On"); } if (i->hasElementDisabledOff()) { - output << indent << iconName << ".addFile(QString::fromUtf8(" - << fixString(i->elementDisabledOff()->text(), indent) - << "), QSize(), QIcon::Disabled, QIcon::Off);\n"; + writeIconAddFile(output, indent, iconName, i->elementDisabledOff()->text(), + "Disabled", "Off"); } if (i->hasElementDisabledOn()) { - output << indent << iconName << ".addFile(QString::fromUtf8(" - << fixString(i->elementDisabledOn()->text(), indent) - << "), QSize(), QIcon::Disabled, QIcon::On);\n"; + writeIconAddFile(output, indent, iconName, i->elementDisabledOn()->text(), + "Disabled", "On"); } if (i->hasElementActiveOff()) { - output << indent << iconName << ".addFile(QString::fromUtf8(" - << fixString(i->elementActiveOff()->text(), indent) - << "), QSize(), QIcon::Active, QIcon::Off);\n"; + writeIconAddFile(output, indent, iconName, i->elementActiveOff()->text(), + "Active", "Off"); } if (i->hasElementActiveOn()) { - output << indent << iconName << ".addFile(QString::fromUtf8(" - << fixString(i->elementActiveOn()->text(), indent) - << "), QSize(), QIcon::Active, QIcon::On);\n"; + writeIconAddFile(output, indent, iconName, i->elementActiveOn()->text(), + "Active", "On"); } if (i->hasElementSelectedOff()) { - output << indent << iconName << ".addFile(QString::fromUtf8(" - << fixString(i->elementSelectedOff()->text(), indent) - << "), QSize(), QIcon::Selected, QIcon::Off);\n"; + writeIconAddFile(output, indent, iconName, i->elementSelectedOff()->text(), + "Selected", "Off"); } if (i->hasElementSelectedOn()) { - output << indent << iconName << ".addFile(QString::fromUtf8(" - << fixString(i->elementSelectedOn()->text(), indent) - << "), QSize(), QIcon::Selected, QIcon::On);\n"; + writeIconAddFile(output, indent, iconName, i->elementSelectedOn()->text(), + "Selected", "On"); } } +static void writeIconAddPixmap(QTextStream &output, const QString &indent, + const QString &iconName, const QString &call, + const char *mode, const char *state) +{ + output << indent << iconName << ".addPixmap(" << call << ", QIcon" + << language::qualifier << mode << ", QIcon" << language::qualifier + << state << ')' << language::eol; +} + void WriteInitialization::writePixmapFunctionIcon(QTextStream &output, const QString &iconName, const QString &indent, const DomResourceIcon *i) const { if (i->hasElementNormalOff()) { - output << indent << iconName << ".addPixmap(" - << pixCall(QLatin1String("QPixmap"), i->elementNormalOff()->text()) - << ", QIcon::Normal, QIcon::Off);\n"; + writeIconAddPixmap(output, indent, iconName, + pixCall(QLatin1String("QPixmap"), i->elementNormalOff()->text()), + "Normal", "Off"); } if (i->hasElementNormalOn()) { - output << indent << iconName << ".addPixmap(" - << pixCall(QLatin1String("QPixmap"), i->elementNormalOn()->text()) - << ", QIcon::Normal, QIcon::On);\n"; + writeIconAddPixmap(output, indent, iconName, + pixCall(QLatin1String("QPixmap"), i->elementNormalOn()->text()), + "Normal", "On"); } if (i->hasElementDisabledOff()) { - output << indent << iconName << ".addPixmap(" - << pixCall(QLatin1String("QPixmap"), i->elementDisabledOff()->text()) - << ", QIcon::Disabled, QIcon::Off);\n"; + writeIconAddPixmap(output, indent, iconName, + pixCall(QLatin1String("QPixmap"), i->elementDisabledOff()->text()), + "Disabled", "Off"); } if (i->hasElementDisabledOn()) { - output << indent << iconName << ".addPixmap(" - << pixCall(QLatin1String("QPixmap"), i->elementDisabledOn()->text()) - << ", QIcon::Disabled, QIcon::On);\n"; + writeIconAddPixmap(output, indent, iconName, + pixCall(QLatin1String("QPixmap"), i->elementDisabledOn()->text()), + "Disabled", "On"); } if (i->hasElementActiveOff()) { - output << indent << iconName << ".addPixmap(" - << pixCall(QLatin1String("QPixmap"), i->elementActiveOff()->text()) - << ", QIcon::Active, QIcon::Off);\n"; + writeIconAddPixmap(output, indent, iconName, + pixCall(QLatin1String("QPixmap"), i->elementActiveOff()->text()), + "Active", "Off"); } if (i->hasElementActiveOn()) { - output << indent << iconName << ".addPixmap(" - << pixCall(QLatin1String("QPixmap"), i->elementActiveOn()->text()) - << ", QIcon::Active, QIcon::On);\n"; + writeIconAddPixmap(output, indent, iconName, + pixCall(QLatin1String("QPixmap"), i->elementActiveOn()->text()), + "Active", "On"); } if (i->hasElementSelectedOff()) { - output << indent << iconName << ".addPixmap(" - << pixCall(QLatin1String("QPixmap"), i->elementSelectedOff()->text()) - << ", QIcon::Selected, QIcon::Off);\n"; + writeIconAddPixmap(output, indent, iconName, + pixCall(QLatin1String("QPixmap"), i->elementSelectedOff()->text()), + "Selected", "Off"); } if (i->hasElementSelectedOn()) { - output << indent << iconName << ".addPixmap(" - << pixCall(QLatin1String("QPixmap"), i->elementSelectedOn()->text()) - << ", QIcon::Selected, QIcon::On);\n"; + writeIconAddPixmap(output, indent, iconName, + pixCall(QLatin1String("QPixmap"), i->elementSelectedOn()->text()), + "Selected", "On"); } } @@ -1691,57 +1746,76 @@ 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()) { + 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"; - if (m_uic->pixmapFunction().isEmpty()) - writeResourceIcon(m_output, iconName, m_indent, i); - else - writePixmapFunctionIcon(m_output, iconName, m_indent, i); - } else { - // Theme: Generate code to check the theme and default to resource - const QString themeIconName = fixString(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 << " = QString::fromUtf8(" - << themeIconName << ");\n"; - m_output << m_indent << "if (QIcon::hasThemeIcon(" - << themeNameStringVariableC - << ")) {\n" - << m_dindent << iconName << " = QIcon::fromTheme(" << themeNameStringVariableC << ");\n" - << m_indent << "} else {\n"; - if (m_uic->pixmapFunction().isEmpty()) - writeResourceIcon(m_output, iconName, m_dindent, i); - else - writePixmapFunctionIcon(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(QString::fromUtf8(" - << 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"; + + const bool isCpp = language::language() == Language::Cpp; + + if (Q_UNLIKELY(!isIconFormat44(i))) { // pre-4.4 legacy + m_output << m_indent; + if (isCpp) + m_output << "const QIcon "; + m_output << iconName << " = " << pixCall(QLatin1String("QIcon"), i->text()) + << language::eol; + return iconName; } + + // 4.4 onwards + if (i->attributeTheme().isEmpty()) { + // No theme: Write resource icon as is + m_output << m_indent << language::stackVariable("QIcon", iconName) + << language::eol; + if (m_uic->pixmapFunction().isEmpty()) + writeResourceIcon(m_output, iconName, m_indent, i); + else + writePixmapFunctionIcon(m_output, iconName, m_indent, i); + return iconName; + } + + // Theme: Generate code to check the theme and default to resource + if (iconHasStatePixmaps(i)) { + // Theme + default state pixmaps: + // Generate code to check the theme and default to state pixmaps + m_output << m_indent << language::stackVariable("QIcon", iconName) << language::eol; + const char themeNameStringVariableC[] = "iconThemeName"; + // Store theme name in a variable + m_output << m_indent; + if (m_firstThemeIcon) { // Declare variable string + if (isCpp) + m_output << "QString "; + m_firstThemeIcon = false; + } + m_output << themeNameStringVariableC << " = " + << language::qstring(i->attributeTheme()) << language::eol; + m_output << m_indent << "if "; + if (isCpp) + m_output << '('; + m_output << "QIcon" << language::qualifier << "hasThemeIcon(" + << themeNameStringVariableC << ')' << (isCpp ? ") {" : ":") << '\n' + << m_dindent << iconName << " = QIcon" << language::qualifier << "fromTheme(" + << themeNameStringVariableC << ')' << language::eol + << m_indent << (isCpp ? "} else {" : "else:") << '\n'; + if (m_uic->pixmapFunction().isEmpty()) + writeResourceIcon(m_output, iconName, m_dindent, i); + else + writePixmapFunctionIcon(m_output, iconName, m_dindent, i); + m_output << m_indent; + if (isCpp) + m_output << '}'; + m_output << '\n'; + return iconName; + } + + // Theme, but no state pixmaps: Construct from theme directly. + m_output << m_indent + << language::stackVariableWithInitParameters("QIcon", iconName) + << "QIcon" << language::qualifier << "fromTheme(" + << language::qstring(i->attributeTheme()) << "))" + << language::eol; return iconName; } @@ -1777,9 +1851,9 @@ void WriteInitialization::writeColorGroup(DomColorGroup *colorGroup, const QStri const DomColor *color = colors.at(i); m_output << m_indent << paletteName << ".setColor(" << group - << ", QPalette::" << language::paletteColorRole(i) + << ", QPalette" << language::qualifier << language::paletteColorRole(i) << ", " << domColor2QString(color) - << ");\n"; + << ")" << language::eol; } // new format @@ -1794,9 +1868,10 @@ void WriteInitialization::writeColorGroup(DomColorGroup *colorGroup, const QStri << versionAdded.majorVersion() << ", " << versionAdded.minorVersion() << ", " << versionAdded.microVersion() << ")\n"; } - m_output << m_indent << paletteName << ".setBrush(" << group - << ", " << "QPalette::" << roleName - << ", " << brushName << ");\n"; + m_output << m_indent << paletteName << ".setBrush(" + << language::enumValue(group) << ", " + << "QPalette" << language::qualifier << roleName + << ", " << brushName << ")" << language::eol; if (!versionAdded.isNull()) m_output << "#endif\n"; } @@ -1842,31 +1917,36 @@ void WriteInitialization::writeBrush(const DomBrush *brush, const QString &brush 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() + m_output << m_indent + << language::stackVariableWithInitParameters("QLinearGradient", gradientName) + << gradient->attributeStartX() << ", " << gradient->attributeStartY() << ", " << gradient->attributeEndX() - << ", " << gradient->attributeEndY() << ");\n"; + << ", " << gradient->attributeEndY() << ')' << language::eol; } else if (gradientType == QLatin1String("RadialGradient")) { - m_output << m_indent << "QRadialGradient " << gradientName - << '(' << gradient->attributeCentralX() + m_output << m_indent + << language::stackVariableWithInitParameters("QRadialGradient", gradientName) + << gradient->attributeCentralX() << ", " << gradient->attributeCentralY() << ", " << gradient->attributeRadius() << ", " << gradient->attributeFocalX() - << ", " << gradient->attributeFocalY() << ");\n"; + << ", " << gradient->attributeFocalY() << ')' << language::eol; } else if (gradientType == QLatin1String("ConicalGradient")) { - m_output << m_indent << "QConicalGradient " << gradientName - << '(' << gradient->attributeCentralX() + m_output << m_indent + << language::stackVariableWithInitParameters("QConicalGradient", gradientName) + << gradient->attributeCentralX() << ", " << gradient->attributeCentralY() - << ", " << gradient->attributeAngle() << ");\n"; + << ", " << gradient->attributeAngle() << ')' << language::eol; } - m_output << m_indent << gradientName << ".setSpread(QGradient::" - << gradient->attributeSpread() << ");\n"; + m_output << m_indent << gradientName << ".setSpread(QGradient" + << language::qualifier << gradient->attributeSpread() + << ')' << language::eol; if (gradient->hasAttributeCoordinateMode()) { - m_output << m_indent << gradientName << ".setCoordinateMode(QGradient::" - << gradient->attributeCoordinateMode() << ");\n"; + m_output << m_indent << gradientName << ".setCoordinateMode(QGradient" + << language::qualifier << gradient->attributeCoordinateMode() + << ')' << language::eol; } const auto &stops = gradient->elementGradientStop(); @@ -1874,23 +1954,26 @@ void WriteInitialization::writeBrush(const DomBrush *brush, const QString &brush const DomColor *color = stop->elementColor(); m_output << m_indent << gradientName << ".setColorAt(" << stop->attributePosition() << ", " - << domColor2QString(color) << ");\n"; + << domColor2QString(color) << ')' << language::eol; } - m_output << m_indent << "QBrush " << brushName << '(' - << gradientName << ");\n"; + m_output << m_indent + << language::stackVariableWithInitParameters("QBrush", brushName) + << gradientName << ')' << language::eol; } else if (style == QLatin1String("TexturePattern")) { const DomProperty *property = brush->elementTexture(); const QString iconValue = iconCall(property); - m_output << m_indent << "QBrush " << brushName << " = QBrush(" - << iconValue << ");\n"; + m_output << m_indent + << language::stackVariableWithInitParameters("QBrush", brushName) + << iconValue << ')' << language::eol; } else { const DomColor *color = brush->elementColor(); - m_output << m_indent << "QBrush " << brushName << '(' - << domColor2QString(color) << ");\n"; + m_output << m_indent + << language::stackVariableWithInitParameters("QBrush", brushName) + << domColor2QString(color) << ')' << language::eol; m_output << m_indent << brushName << ".setStyle(" - << "Qt::" << style << ");\n"; + << language::qtQualifier << style << ')' << language::eol; } } @@ -1910,12 +1993,11 @@ void WriteInitialization::acceptTabStops(DomTabStops *tabStops) const QStringList l = tabStops->elementTabStop(); for (int i=0; i<l.size(); ++i) { - const QString &name = l.at(i); + const QString name = m_driver->widgetVariableName(l.at(i)); - if (!m_registeredWidgets.contains(name)) { + if (name.isEmpty()) { fprintf(stderr, "%s: Warning: Tab-stop assignment: '%s' is not a valid widget.\n", - qPrintable(m_option.messagePrefix()), - name.toLatin1().data()); + qPrintable(m_option.messagePrefix()), qPrintable(l.at(i))); continue; } @@ -1926,7 +2008,8 @@ void WriteInitialization::acceptTabStops(DomTabStops *tabStops) if (name.isEmpty() || lastName.isEmpty()) continue; - m_output << m_indent << "QWidget::setTabOrder(" << lastName << ", " << name << ");\n"; + m_output << m_indent << "QWidget" << language::qualifier << "setTabOrder(" + << lastName << ", " << name << ')' << language::eol; lastName = name; } @@ -1968,15 +2051,14 @@ QString WriteInitialization::pixCall(const QString &t, const QString &text) cons return type; } + QTextStream str(&type); + str << '('; QString pixFunc = m_uic->pixmapFunction(); if (pixFunc.isEmpty()) - pixFunc = QLatin1String("QString::fromUtf8"); - - type += QLatin1Char('(') - + pixFunc - + QLatin1Char('(') - + fixString(text, m_dindent) - + QLatin1String("))"); + str << language::qstring(text, m_dindent); + else + str << pixFunc << '(' << language::charliteral(text, m_dindent) << ')'; + str << ')'; return type; } @@ -1999,15 +2081,17 @@ void WriteInitialization::initializeComboBox(DomWidget *w) if (icon) iconValue = iconCall(icon); - m_output << m_indent << varName << "->addItem("; + m_output << m_indent << varName << language::derefPointer << "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"; + m_output << "QString())" << language::eol; + m_refreshOut << m_indent << varName << language::derefPointer + << "setItemText(" << i << ", " << trCall(text->elementString()) + << ')' << language::eol; } else { - m_output << noTrCall(text->elementString()) << ");\n"; + m_output << noTrCall(text->elementString()) << ")" << language::eol; } } m_refreshOut << "\n"; @@ -2020,9 +2104,13 @@ QString WriteInitialization::disableSorting(DomWidget *w, const QString &varName 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"; + m_refreshOut << m_indent; + if (language::language() == Language::Cpp) + m_refreshOut << "const bool "; + m_refreshOut << tempName << " = " << varName << language::derefPointer + << "isSortingEnabled()" << language::eol + << m_indent << varName << language::derefPointer + << "setSortingEnabled(" << language::boolValue(false) << ')' << language::eol; } return tempName; } @@ -2030,7 +2118,8 @@ QString WriteInitialization::disableSorting(DomWidget *w, const QString &varName void WriteInitialization::enableSorting(DomWidget *w, const QString &varName, const QString &tempName) { if (!w->elementItem().isEmpty()) { - m_refreshOut << m_indent << varName << "->setSortingEnabled(" << tempName << ");\n\n"; + m_refreshOut << m_indent << varName << language::derefPointer + << "setSortingEnabled(" << tempName << ')' << language::eol << '\n'; } } @@ -2055,7 +2144,7 @@ void WriteInitialization::addInitializer(Item *item, if (!value.isEmpty()) { QString setter; QTextStream str(&setter); - str << "->set" << name.at(0).toUpper() << name.midRef(1) << '('; + str << language::derefPointer << "set" << name.at(0).toUpper() << name.midRef(1) << '('; if (column >= 0) str << column << ", "; str << value << ");"; @@ -2105,10 +2194,11 @@ void WriteInitialization::addQtFlagsInitializer(Item *item, const DomPropertyMap &properties, const QString &name, int column) const { if (const DomProperty *p = properties.value(name)) { + const QString orOperator = QLatin1Char('|') + language::qtQualifier; QString v = p->elementSet(); if (!v.isEmpty()) { - v.replace(QLatin1Char('|'), QLatin1String("|Qt::")); - addInitializer(item, name, column, QLatin1String("Qt::") + v); + v.replace(QLatin1Char('|'), orOperator); + addInitializer(item, name, column, language::qtQualifier + v); } } } @@ -2123,7 +2213,7 @@ void WriteInitialization::addQtEnumInitializer(Item *item, if (const DomProperty *p = properties.value(name)) { QString v = p->elementEnum(); if (!v.isEmpty()) - addInitializer(item, name, column, QLatin1String("Qt::") + v); + addInitializer(item, name, column, language::qtQualifier + v); } } @@ -2172,7 +2262,9 @@ void WriteInitialization::initializeListWidget(DomWidget *w) addCommonInitializers(&item, properties); item.writeSetupUi(varName); - item.writeRetranslateUi(varName + QLatin1String("->item(") + QString::number(i) + QLatin1Char(')')); + QString parentPath; + QTextStream(&parentPath) << varName << language::derefPointer << "item(" << i << ')'; + item.writeRetranslateUi(parentPath); } enableSorting(w, varName, tempName); } @@ -2193,14 +2285,19 @@ void WriteInitialization::initializeTreeWidget(DomWidget *w) 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"; + if (str && str->text().isEmpty()) { + m_output << m_indent << varName << language::derefPointer + << "headerItem()" << language::derefPointer << "setText(" + << i << ", QString())" << language::eol; + } } } const QString itemName = item.writeSetupUi(QString(), Item::DontConstruct); - item.writeRetranslateUi(varName + QLatin1String("->headerItem()")); - if (!itemName.isNull()) - m_output << m_indent << varName << "->setHeaderItem(" << itemName << ");\n"; + item.writeRetranslateUi(varName + language::derefPointer + QLatin1String("headerItem()")); + if (!itemName.isNull()) { + m_output << m_indent << varName << language::derefPointer + << "setHeaderItem(" << itemName << ')' << language::eol; + } if (w->elementItem().empty()) return; @@ -2211,7 +2308,9 @@ void WriteInitialization::initializeTreeWidget(DomWidget *w) for (int i = 0; i < items.count(); i++) { Item *itm = items[i]; itm->writeSetupUi(varName); - itm->writeRetranslateUi(varName + QLatin1String("->topLevelItem(") + QString::number(i) + QLatin1Char(')')); + QString parentPath; + QTextStream(&parentPath) << varName << language::derefPointer << "topLevelItem(" << i << ')'; + itm->writeRetranslateUi(parentPath); delete itm; } @@ -2273,8 +2372,10 @@ void WriteInitialization::initializeTableWidget(DomWidget *w) const auto &columns = w->elementColumn(); if (!columns.empty()) { - m_output << m_indent << "if (" << varName << "->columnCount() < " << columns.size() << ")\n" - << m_dindent << varName << "->setColumnCount(" << columns.size() << ");\n"; + m_output << m_indent << "if (" << varName << language::derefPointer << "columnCount() < " + << columns.size() << ")\n" + << m_dindent << varName << language::derefPointer << "setColumnCount(" + << columns.size() << ')' << language::eol; } for (int i = 0; i < columns.size(); ++i) { @@ -2286,8 +2387,12 @@ void WriteInitialization::initializeTableWidget(DomWidget *w) 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(" << i << ", " << itemName << ");\n"; + QString parentPath; + QTextStream(&parentPath) << varName << language::derefPointer + << "horizontalHeaderItem(" << i << ')'; + item.writeRetranslateUi(parentPath); + m_output << m_indent << varName << language::derefPointer << "setHorizontalHeaderItem(" + << i << ", " << itemName << ')' << language::eol; } } @@ -2295,8 +2400,9 @@ void WriteInitialization::initializeTableWidget(DomWidget *w) const auto &rows = w->elementRow(); if (!rows.isEmpty()) { - m_output << m_indent << "if (" << varName << "->rowCount() < " << rows.size() << ")\n" - << m_dindent << varName << "->setRowCount(" << rows.size() << ");\n"; + m_output << m_indent << "if (" << varName << language::derefPointer << "rowCount() < " << rows.size() << ")\n" + << m_dindent << varName << language::derefPointer << "setRowCount(" + << rows.size() << ')' << language::eol; } for (int i = 0; i < rows.size(); ++i) { @@ -2308,8 +2414,11 @@ void WriteInitialization::initializeTableWidget(DomWidget *w) 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(" << i << ", " << itemName << ");\n"; + QString parentPath; + QTextStream(&parentPath) << varName << language::derefPointer << "verticalHeaderItem(" << i << ')'; + item.writeRetranslateUi(parentPath); + m_output << m_indent << varName << language::derefPointer << "setVerticalHeaderItem(" + << i << ", " << itemName << ')' << language::eol; } } @@ -2329,8 +2438,12 @@ void WriteInitialization::initializeTableWidget(DomWidget *w) 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(" << r << ", " << c << ", " << itemName << ");\n"; + QString parentPath; + QTextStream(&parentPath) << varName << language::derefPointer << "item(" << r + << ", " << c << ')'; + item.writeRetranslateUi(parentPath); + m_output << m_indent << varName << language::derefPointer << "setItem(" + << r << ", " << c << ", " << itemName << ')' << language::eol; } } enableSorting(w, varName, tempName); @@ -2338,32 +2451,37 @@ void WriteInitialization::initializeTableWidget(DomWidget *w) QString WriteInitialization::trCall(const QString &str, const QString &commentHint, const QString &id) const { - if (str.isEmpty()) - return QLatin1String("QString()"); + if (str.isEmpty()) { + return language::language() == Language::Cpp + ? QLatin1String("QString()") : QLatin1String("\"\""); + } QString result; - const QString comment = commentHint.isEmpty() ? QString(QLatin1String("nullptr")) : fixString(commentHint, m_dindent); + QTextStream ts(&result); const bool idBasedTranslations = m_driver->useIdBasedTranslations(); if (m_option.translateFunction.isEmpty()) { if (idBasedTranslations || m_option.idBased) { - result += QLatin1String("qtTrId("); + ts << "qtTrId("; } else { - result += QLatin1String("QCoreApplication::translate(\"") - + m_generatedClass - + QLatin1String("\", "); + ts << "QCoreApplication" << language::qualifier << "translate(" + << '"' << m_generatedClass << "\", "; } } else { - result += m_option.translateFunction + QLatin1Char('('); + ts << m_option.translateFunction << '('; } - result += fixString(idBasedTranslations ? id : str, m_dindent); + ts << language::charliteral(idBasedTranslations ? id : str, m_dindent); if (!idBasedTranslations && !m_option.idBased) { - result += QLatin1String(", ") + comment; + ts << ", "; + if (commentHint.isEmpty()) + ts << language::nullPtr; + else + ts << language::charliteral(commentHint, m_dindent); } - result += QLatin1Char(')'); + ts << ')'; return result; } @@ -2374,7 +2492,8 @@ void WriteInitialization::initializeMenu(DomWidget *w, const QString &/*parentWi const DomAction *action = m_driver->actionByName(menuAction); if (action && action->hasAttributeMenu()) { - m_output << m_indent << menuAction << " = " << menuName << "->menuAction();\n"; + m_output << m_indent << menuAction << " = " << menuName + << language::derefPointer << "menuAction()" << language::eol; } } @@ -2398,9 +2517,9 @@ QString WriteInitialization::noTrCall(DomString *str, const QString &defaultStri return QString(); if (str) value = str->text(); - QString ret = QLatin1String("QString::fromUtf8("); - ret += fixString(value, m_dindent); - ret += QLatin1Char(')'); + QString ret; + QTextStream ts(&ret); + ts << language::qstring(value, m_dindent); return ret; } @@ -2428,36 +2547,42 @@ QTextStream &WriteInitialization::autoTrOutput(const DomString *str, const QStri return m_output; } -QString WriteInitialization::findDeclaration(const QString &name) +WriteInitialization::Declaration WriteInitialization::findDeclaration(const QString &name) { - const QString normalized = Driver::normalizedName(name); - - if (const DomWidget *widget = m_driver->widgetByName(normalized)) - return m_driver->findOrInsertWidget(widget); - if (const 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(); + if (const DomWidget *widget = m_driver->widgetByName(name)) + return {m_driver->findOrInsertWidget(widget), widget->attributeClass()}; + if (const DomAction *action = m_driver->actionByName(name)) + return {m_driver->findOrInsertAction(action), QStringLiteral("QAction")}; + if (const DomButtonGroup *group = m_driver->findButtonGroup(name)) + return {m_driver->findOrInsertButtonGroup(group), QStringLiteral("QButtonGroup")}; + return {}; } void WriteInitialization::acceptConnection(DomConnection *connection) { - const QString sender = findDeclaration(connection->elementSender()); - const QString receiver = findDeclaration(connection->elementReceiver()); + const QString senderName = connection->elementSender(); + const QString receiverName = connection->elementReceiver(); - if (sender.isEmpty() || receiver.isEmpty()) + const auto senderDecl = findDeclaration(senderName); + const auto receiverDecl = findDeclaration(receiverName); + + if (senderDecl.name.isEmpty() || receiverDecl.name.isEmpty()) { + QString message; + QTextStream(&message) << m_option.messagePrefix() + << ": Warning: Invalid signal/slot connection: \"" + << senderName << "\" -> \"" << receiverName << "\"."; + fprintf(stderr, "%s\n", qPrintable(message)); return; + } - m_output << m_indent << "QObject::connect(" - << sender - << ", " - << "SIGNAL("<<connection->elementSignal()<<')' - << ", " - << receiver - << ", " - << "SLOT("<<connection->elementSlot()<<')' - << ");\n"; + language::SignalSlot theSignal{senderDecl.name, connection->elementSignal(), + senderDecl.className}; + language::SignalSlot theSlot{receiverDecl.name, connection->elementSlot(), + receiverDecl.className}; + + m_output << m_indent; + language::formatConnection(m_output, theSignal, theSlot); + m_output << language::eol; } static void generateMultiDirectiveBegin(QTextStream &outputStream, const QSet<QString> &directives) @@ -2470,14 +2595,14 @@ static void generateMultiDirectiveBegin(QTextStream &outputStream, const QSet<QS return; } - auto list = directives.toList(); + auto list = directives.values(); // sort (always generate in the same order): std::sort(list.begin(), list.end()); outputStream << "#if " << language::qtConfig(list.constFirst()); for (int i = 1, size = list.size(); i < size; ++i) outputStream << " || " << language::qtConfig(list.at(i)); - outputStream << endl; + outputStream << Qt::endl; } static void generateMultiDirectiveEnd(QTextStream &outputStream, const QSet<QString> &directives) @@ -2485,12 +2610,11 @@ static void generateMultiDirectiveEnd(QTextStream &outputStream, const QSet<QStr if (directives.isEmpty()) return; - outputStream << "#endif" << endl; + outputStream << "#endif" << Qt::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), @@ -2513,7 +2637,8 @@ QString WriteInitialization::Item::writeSetupUi(const QString &parent, Item::Emp bool generateMultiDirective = false; if (emptyItemPolicy == Item::ConstructItemOnly && m_children.isEmpty()) { if (m_setupUiData.policy == ItemData::DontGenerate) { - m_setupUiStream << m_indent << "new " << m_itemClassName << '(' << parent << ");\n"; + m_setupUiStream << m_indent << language::operatorNew << m_itemClassName + << '(' << parent << ')' << language::eol; return QString(); } if (m_setupUiData.policy == ItemData::GenerateWithMultiDirective) @@ -2524,11 +2649,17 @@ QString WriteInitialization::Item::writeSetupUi(const QString &parent, Item::Emp 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"; + m_setupUiStream << m_indent; + if (language::language() == Language::Cpp) + m_setupUiStream << m_itemClassName << " *"; + m_setupUiStream << uniqueName + << " = " << language::operatorNew << m_itemClassName << '(' << parent + << ')' << language::eol; if (generateMultiDirective) { m_setupUiStream << "#else\n"; - m_setupUiStream << m_indent << "new " << m_itemClassName << '(' << parent << ");\n"; + m_setupUiStream << m_indent << language::operatorNew << m_itemClassName + << '(' << parent << ')' << language::eol; generateMultiDirectiveEnd(m_setupUiStream, m_setupUiData.directives); } @@ -2536,7 +2667,7 @@ QString WriteInitialization::Item::writeSetupUi(const QString &parent, Item::Emp while (it != m_setupUiData.setters.constEnd()) { if (!it.key().isEmpty()) m_setupUiStream << language::openQtConfig(it.key()); - m_setupUiStream << m_indent << uniqueName << it.value() << endl; + m_setupUiStream << m_indent << uniqueName << it.value() << Qt::endl; if (!it.key().isEmpty()) m_setupUiStream << language::closeQtConfig(it.key()); ++it; @@ -2555,7 +2686,10 @@ void WriteInitialization::Item::writeRetranslateUi(const QString &parentPath) 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"; + m_retranslateUiStream << m_indent; + if (language::language() == Language::Cpp) + m_retranslateUiStream << m_itemClassName << " *"; + m_retranslateUiStream << uniqueName << " = " << parentPath << language::eol; if (m_retranslateUiData.policy == ItemData::GenerateWithMultiDirective) generateMultiDirectiveEnd(m_retranslateUiStream, m_retranslateUiData.directives); @@ -2571,14 +2705,17 @@ void WriteInitialization::Item::writeRetranslateUi(const QString &parentPath) m_retranslateUiStream << language::openQtConfig(newDirective); oldDirective = newDirective; } - m_retranslateUiStream << m_indent << uniqueName << it.value() << endl; + m_retranslateUiStream << m_indent << uniqueName << it.value() << Qt::endl; ++it; } if (!oldDirective.isEmpty()) m_retranslateUiStream << language::closeQtConfig(oldDirective); - for (int i = 0; i < m_children.size(); i++) - m_children[i]->writeRetranslateUi(uniqueName + QLatin1String("->child(") + QString::number(i) + QLatin1Char(')')); + for (int i = 0; i < m_children.size(); i++) { + QString method; + QTextStream(&method) << uniqueName << language::derefPointer << "child(" << i << ')'; + m_children[i]->writeRetranslateUi(method); + } } void WriteInitialization::Item::addSetter(const QString &setter, const QString &directive, bool translatable) diff --git a/src/tools/uic/cpp/cppwriteinitialization.h b/src/tools/uic/cpp/cppwriteinitialization.h index c408c44b40..6f8e352f6a 100644 --- a/src/tools/uic/cpp/cppwriteinitialization.h +++ b/src/tools/uic/cpp/cppwriteinitialization.h @@ -85,8 +85,8 @@ namespace CPP { struct WriteInitialization : public TreeWalker { - typedef QList<DomProperty*> DomPropertyList; - typedef QHash<QString, DomProperty*> DomPropertyMap; + using DomPropertyList = QList<DomProperty*>; + using DomPropertyMap = QHash<QString, DomProperty*>; WriteInitialization(Uic *uic); @@ -161,7 +161,7 @@ private: // special initialization // class Item { - Q_DISABLE_COPY(Item) + Q_DISABLE_COPY_MOVE(Item) public: Item(const QString &itemClassName, const QString &indent, QTextStream &setupUiStream, QTextStream &retranslateUiStream, Driver *driver); ~Item(); @@ -188,7 +188,7 @@ private: ItemData m_setupUiData; ItemData m_retranslateUiData; QList<Item *> m_children; - Item *m_parent; + Item *m_parent = nullptr; const QString m_itemClassName; const QString m_indent; @@ -220,7 +220,13 @@ private: QString disableSorting(DomWidget *w, const QString &varName); void enableSorting(DomWidget *w, const QString &varName, const QString &tempName); - QString findDeclaration(const QString &name); + struct Declaration + { + QString name; + QString className; + }; + + Declaration findDeclaration(const QString &name); private: QString writeFontProperties(const DomFont *f); @@ -238,12 +244,12 @@ private: const Option &m_option; QString m_indent; QString m_dindent; - bool m_stdsetdef; + bool m_stdsetdef = true; struct Buddy { - QString objName; - QString buddy; + QString labelVarName; + QString buddyAttributeName; }; friend class QTypeInfo<Buddy>; @@ -253,15 +259,13 @@ private: QVector<Buddy> m_buddies; QSet<QString> m_buttonGroups; - QHash<QString, DomWidget*> m_registeredWidgets; - QHash<QString, DomAction*> m_registeredActions; - typedef QHash<uint, QString> ColorBrushHash; + using ColorBrushHash = QHash<uint, QString>; ColorBrushHash m_colorBrushHash; // Map from font properties to font variable name for reuse // Map from size policy to variable for reuse - typedef QMap<FontHandle, QString> FontPropertiesNameMap; - typedef QMap<IconHandle, QString> IconPropertiesNameMap; - typedef QMap<SizePolicyHandle, QString> SizePolicyNameMap; + using FontPropertiesNameMap = QMap<FontHandle, QString>; + using IconPropertiesNameMap = QMap<IconHandle, QString>; + using SizePolicyNameMap = QMap<SizePolicyHandle, QString>; FontPropertiesNameMap m_fontPropertiesNameMap; IconPropertiesNameMap m_iconPropertiesNameMap; SizePolicyNameMap m_sizePolicyNameMap; @@ -290,11 +294,11 @@ private: // layout defaults LayoutDefaultHandler m_LayoutDefaultHandler; - int m_layoutMarginType; + int m_layoutMarginType = TopLevelMargin; QString m_generatedClass; QString m_mainFormVarName; - bool m_mainFormUsedInRetranslateUi; + bool m_mainFormUsedInRetranslateUi = false; QString m_delayedInitialization; QTextStream m_delayedOut; @@ -305,8 +309,9 @@ private: QString m_delayedActionInitialization; QTextStream m_actionOut; - bool m_layoutWidget; - bool m_firstThemeIcon; + bool m_layoutWidget = false; + bool m_firstThemeIcon = true; + bool m_connectSlotsByName = true; }; } // namespace CPP diff --git a/src/tools/uic/customwidgetsinfo.cpp b/src/tools/uic/customwidgetsinfo.cpp index d6a409152b..c838feaf73 100644 --- a/src/tools/uic/customwidgetsinfo.cpp +++ b/src/tools/uic/customwidgetsinfo.cpp @@ -95,7 +95,7 @@ bool CustomWidgetsInfo::extendsOneOf(const QString &classNameIn, bool CustomWidgetsInfo::isCustomWidgetContainer(const QString &className) const { - if (const DomCustomWidget *dcw = m_customWidgets.value(className, 0)) + if (const DomCustomWidget *dcw = m_customWidgets.value(className, nullptr)) if (dcw->hasElementContainer()) return dcw->elementContainer() != 0; return false; @@ -111,7 +111,7 @@ QString CustomWidgetsInfo::realClassName(const QString &className) const QString CustomWidgetsInfo::customWidgetAddPageMethod(const QString &name) const { - if (DomCustomWidget *dcw = m_customWidgets.value(name, 0)) + if (DomCustomWidget *dcw = m_customWidgets.value(name, nullptr)) return dcw->elementAddPageMethod(); return QString(); } diff --git a/src/tools/uic/customwidgetsinfo.h b/src/tools/uic/customwidgetsinfo.h index 8a10999027..a1b24ab042 100644 --- a/src/tools/uic/customwidgetsinfo.h +++ b/src/tools/uic/customwidgetsinfo.h @@ -62,7 +62,7 @@ public: bool isCustomWidgetContainer(const QString &className) const; private: - typedef QMap<QString, DomCustomWidget*> NameCustomWidgetMap; + using NameCustomWidgetMap = QMap<QString, DomCustomWidget*>; NameCustomWidgetMap m_customWidgets; }; diff --git a/src/tools/uic/databaseinfo.cpp b/src/tools/uic/databaseinfo.cpp index fa5d5f5df0..9b0d1614ab 100644 --- a/src/tools/uic/databaseinfo.cpp +++ b/src/tools/uic/databaseinfo.cpp @@ -33,9 +33,7 @@ QT_BEGIN_NAMESPACE -DatabaseInfo::DatabaseInfo() -{ -} +DatabaseInfo::DatabaseInfo() = default; void DatabaseInfo::acceptUI(DomUI *node) { @@ -59,10 +57,9 @@ void DatabaseInfo::acceptWidget(DomWidget *node) DomProperty *db = properties.value(QLatin1String("database")); if (db && db->elementStringList()) { QStringList info = db->elementStringList()->elementString(); - - QString connection = info.size() > 0 ? info.at(0) : QString(); - if (connection.isEmpty()) + if (info.isEmpty() || info.constFirst().isEmpty()) return; + const QString &connection = info.constFirst(); m_connections.append(connection); QString table = info.size() > 1 ? info.at(1) : QString(); diff --git a/src/tools/uic/driver.cpp b/src/tools/uic/driver.cpp index 03fa1e17cf..8b9b4806e6 100644 --- a/src/tools/uic/driver.cpp +++ b/src/tools/uic/driver.cpp @@ -30,6 +30,8 @@ #include "uic.h" #include "ui4.h" +#include <language.h> + #include <qfileinfo.h> #include <qdebug.h> @@ -51,18 +53,43 @@ static inline QString actionClass() { return QStringLiteral("QAction"); } static inline QString buttonGroupClass() { return QStringLiteral("QButtonGroup"); } template <class DomClass> +Driver::DomObjectHashConstIt<DomClass> + Driver::findByAttributeNameIt(const DomObjectHash<DomClass> &domHash, + const QString &name) const +{ + const auto end = domHash.cend(); + for (auto it = domHash.cbegin(); it != end; ++it) { + if (it.key()->attributeName() == name) + return it; + } + return end; +} + +template <class DomClass> +const DomClass *Driver::findByAttributeName(const DomObjectHash<DomClass> &domHash, + const QString &name) const +{ + auto it = findByAttributeNameIt(domHash, name); + return it != domHash.cend() ? it.key() : nullptr; +} + +template <class DomClass> QString Driver::findOrInsert(DomObjectHash<DomClass> *domHash, const DomClass *dom, - const QString &className) + const QString &className, bool isMember) { auto it = domHash->find(dom); - if (it == domHash->end()) - it = domHash->insert(dom, this->unique(dom->attributeName(), className)); + if (it == domHash->end()) { + const QString name = this->unique(dom->attributeName(), className); + it = domHash->insert(dom, isMember ? language::self + name : name); + } return it.value(); } QString Driver::findOrInsertWidget(const DomWidget *ui_widget) { - return findOrInsert(&m_widgets, ui_widget, ui_widget->attributeClass()); + // Top level is passed into setupUI(), everything else is a member variable + const bool isMember = !m_widgets.isEmpty(); + return findOrInsert(&m_widgets, ui_widget, ui_widget->attributeClass(), isMember); } QString Driver::findOrInsertSpacer(const DomSpacer *ui_spacer) @@ -111,11 +138,7 @@ QString Driver::findOrInsertButtonGroup(const DomButtonGroup *ui_group) // Find a group by its non-uniqified name const DomButtonGroup *Driver::findButtonGroup(const QString &attributeName) const { - for (auto it = m_buttonGroups.cbegin(), end = m_buttonGroups.cend(); it != end; ++it) { - if (it.key()->attributeName() == attributeName) - return it.key(); - } - return nullptr; + return findByAttributeName(m_buttonGroups, attributeName); } @@ -233,7 +256,7 @@ bool Driver::uic(const QString &fileName, DomUI *ui, QTextStream *out) QTextStream *oldOutput = m_output; - m_output = out != 0 ? out : &m_stdout; + m_output = out != nullptr ? out : &m_stdout; Uic tool(this); const bool result = tool.write(ui); @@ -286,19 +309,25 @@ bool Driver::uic(const QString &fileName, QTextStream *out) return rtn; } -const DomWidget *Driver::widgetByName(const QString &name) const +const DomWidget *Driver::widgetByName(const QString &attributeName) const +{ + return findByAttributeName(m_widgets, attributeName); +} + +QString Driver::widgetVariableName(const QString &attributeName) const { - return m_widgets.key(name); + auto it = findByAttributeNameIt(m_widgets, attributeName); + return it != m_widgets.cend() ? it.value() : QString(); } -const DomActionGroup *Driver::actionGroupByName(const QString &name) const +const DomActionGroup *Driver::actionGroupByName(const QString &attributeName) const { - return m_actionGroups.key(name); + return findByAttributeName(m_actionGroups, attributeName); } -const DomAction *Driver::actionByName(const QString &name) const +const DomAction *Driver::actionByName(const QString &attributeName) const { - return m_actions.key(name); + return findByAttributeName(m_actions, attributeName); } QT_END_NAMESPACE diff --git a/src/tools/uic/driver.h b/src/tools/uic/driver.h index 1303d0bf8a..45ec23b4aa 100644 --- a/src/tools/uic/driver.h +++ b/src/tools/uic/driver.h @@ -56,8 +56,8 @@ public: // tools bool printDependencies(const QString &fileName); - bool uic(const QString &fileName, QTextStream *output = 0); - bool uic(const QString &fileName, DomUI *ui, QTextStream *output = 0); + bool uic(const QString &fileName, QTextStream *output = nullptr); + bool uic(const QString &fileName, DomUI *ui, QTextStream *output = nullptr); // configuration inline QTextStream &output() const { return *m_output; } @@ -84,18 +84,28 @@ public: // Find a group by its non-uniqified name const DomButtonGroup *findButtonGroup(const QString &attributeName) const; - const DomWidget *widgetByName(const QString &name) const; - const DomActionGroup *actionGroupByName(const QString &name) const; - const DomAction *actionByName(const QString &name) const; + const DomWidget *widgetByName(const QString &attributeName) const; + QString widgetVariableName(const QString &attributeName) const; + const DomActionGroup *actionGroupByName(const QString &attributeName) const; + const DomAction *actionByName(const QString &attributeName) const; bool useIdBasedTranslations() const { return m_idBasedTranslations; } void setUseIdBasedTranslations(bool u) { m_idBasedTranslations = u; } private: template <class DomClass> using DomObjectHash = QHash<const DomClass *, QString>; + template <class DomClass> using DomObjectHashConstIt = + typename DomObjectHash<DomClass>::ConstIterator; template <class DomClass> - QString findOrInsert(DomObjectHash<DomClass> *domHash, const DomClass *dom, const QString &className); + DomObjectHashConstIt<DomClass> findByAttributeNameIt(const DomObjectHash<DomClass> &domHash, + const QString &name) const; + template <class DomClass> + const DomClass *findByAttributeName(const DomObjectHash<DomClass> &domHash, + const QString &name) const; + template <class DomClass> + QString findOrInsert(DomObjectHash<DomClass> *domHash, const DomClass *dom, const QString &className, + bool isMember = true); Option m_option; QTextStream m_stdout; diff --git a/src/tools/uic/main.cpp b/src/tools/uic/main.cpp index 0516b854ff..9cf22d502d 100644 --- a/src/tools/uic/main.cpp +++ b/src/tools/uic/main.cpp @@ -29,6 +29,7 @@ #include "uic.h" #include "option.h" #include "driver.h" +#include <language.h> #include <qfile.h> #include <qdir.h> @@ -67,6 +68,10 @@ int runUic(int argc, char *argv[]) outputOption.setValueName(QStringLiteral("file")); parser.addOption(outputOption); + QCommandLineOption noAutoConnectionOption(QStringList() << QStringLiteral("a") << QStringLiteral("no-autoconnection")); + noAutoConnectionOption.setDescription(QStringLiteral("Do not generate a call to QObject::connectSlotsByName().")); + parser.addOption(noAutoConnectionOption); + QCommandLineOption noProtOption(QStringList() << QStringLiteral("p") << QStringLiteral("no-protection")); noProtOption.setDescription(QStringLiteral("Disable header protection.")); parser.addOption(noProtOption); @@ -96,7 +101,7 @@ int runUic(int argc, char *argv[]) QCommandLineOption generatorOption(QStringList() << QStringLiteral("g") << QStringLiteral("generator")); generatorOption.setDescription(QStringLiteral("Select generator.")); - generatorOption.setValueName(QStringLiteral("java|cpp")); + generatorOption.setValueName(QStringLiteral("python|cpp")); parser.addOption(generatorOption); QCommandLineOption idBasedOption(QStringLiteral("idbased")); @@ -109,6 +114,7 @@ int runUic(int argc, char *argv[]) driver.option().dependencies = parser.isSet(dependenciesOption); driver.option().outputFile = parser.value(outputOption); + driver.option().autoConnection = !parser.isSet(noAutoConnectionOption); driver.option().headerProtection = !parser.isSet(noProtOption); driver.option().implicitIncludes = !parser.isSet(noImplicitIncludesOption); driver.option().idBased = parser.isSet(idBasedOption); @@ -116,6 +122,13 @@ int runUic(int argc, char *argv[]) driver.option().translateFunction = parser.value(translateOption); driver.option().includeFile = parser.value(includeOption); + Language language = Language::Cpp; + if (parser.isSet(generatorOption)) { + if (parser.value(generatorOption).compare(QLatin1String("python")) == 0) + language = Language::Python; + } + language::setLanguage(language); + if (parser.isSet(noStringLiteralOption)) fprintf(stderr, "The -s, --no-stringliteral option is deprecated and it won't take any effect.\n"); @@ -129,7 +142,7 @@ int runUic(int argc, char *argv[]) return !driver.printDependencies(inputFile); } - QTextStream *out = 0; + QTextStream *out = nullptr; QFile f; if (!driver.option().outputFile.isEmpty()) { f.setFileName(driver.option().outputFile); diff --git a/src/tools/uic/python/python.pri b/src/tools/uic/python/python.pri new file mode 100644 index 0000000000..4dd31160a1 --- /dev/null +++ b/src/tools/uic/python/python.pri @@ -0,0 +1,8 @@ +INCLUDEPATH += $$PWD + +# Input +HEADERS += $$PWD/pythonwritedeclaration.h \ + $$PWD/pythonwriteimports.h + +SOURCES += $$PWD/pythonwritedeclaration.cpp \ + $$PWD/pythonwriteimports.cpp diff --git a/src/tools/uic/python/pythonwritedeclaration.cpp b/src/tools/uic/python/pythonwritedeclaration.cpp new file mode 100644 index 0000000000..5122b18e23 --- /dev/null +++ b/src/tools/uic/python/pythonwritedeclaration.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 "pythonwritedeclaration.h" +#include <cppwriteinitialization.h> +#include <language.h> +#include <driver.h> +#include <ui4.h> +#include <uic.h> + +#include <QtCore/qtextstream.h> +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +namespace Python { + +WriteDeclaration::WriteDeclaration(Uic *uic) : + m_uic(uic), + m_driver(uic->driver()), + m_output(uic->output()), + m_option(uic->option()) +{ +} + +void WriteDeclaration::acceptUI(DomUI *node) +{ + // remove any left-over C++ namespaces + const QString qualifiedClassName = QLatin1String("Ui_") + node->elementClass() + + m_option.postfix; + m_output << "class " << language::fixClassName(qualifiedClassName) << "(object):\n"; + + TreeWalker::acceptWidget(node->elementWidget()); + if (const DomButtonGroups *domButtonGroups = node->elementButtonGroups()) + acceptButtonGroups(domButtonGroups); + CPP::WriteInitialization(m_uic).acceptUI(node); +} + +// Register button groups to prevent the on-the-fly creation legacy +// feature from triggering +void WriteDeclaration::acceptButtonGroup(const DomButtonGroup *buttonGroup) +{ + m_driver->findOrInsertButtonGroup(buttonGroup); +} + +} // namespace Python + +QT_END_NAMESPACE diff --git a/src/tools/uic/python/pythonwritedeclaration.h b/src/tools/uic/python/pythonwritedeclaration.h new file mode 100644 index 0000000000..a8d50b6fbf --- /dev/null +++ b/src/tools/uic/python/pythonwritedeclaration.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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$ +** +****************************************************************************/ + +#ifndef PYTHONWRITEDECLARATION_H +#define PYTHONWRITEDECLARATION_H + +#include <treewalker.h> + +QT_BEGIN_NAMESPACE + +class QTextStream; +class Driver; +class Uic; + +struct Option; + +namespace Python { + +struct WriteDeclaration : public TreeWalker +{ + WriteDeclaration(Uic *uic); + + void acceptUI(DomUI *node) override; + void acceptButtonGroup(const DomButtonGroup *buttonGroup) override; + +private: + Uic *m_uic; + Driver *m_driver; + QTextStream &m_output; + const Option &m_option; +}; + +} // namespace Python + +QT_END_NAMESPACE + +#endif // PYTHONWRITEDECLARATION_H diff --git a/src/tools/uic/python/pythonwriteimports.cpp b/src/tools/uic/python/pythonwriteimports.cpp new file mode 100644 index 0000000000..303615f77b --- /dev/null +++ b/src/tools/uic/python/pythonwriteimports.cpp @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 "pythonwriteimports.h" + +#include <customwidgetsinfo.h> +#include <uic.h> + +#include <ui4.h> + +#include <QtCore/qtextstream.h> + +QT_BEGIN_NAMESPACE + +static const char *standardImports = +R"I(from PySide2.QtCore import (QCoreApplication, QMetaObject, QObject, QPoint, + QRect, QSize, QUrl, Qt) +from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QFont, + QFontDatabase, QIcon, QLinearGradient, QPalette, QPainter, QPixmap, + QRadialGradient) +from PySide2.QtWidgets import * +)I"; + +namespace Python { + +WriteImports::WriteImports(Uic *uic) : m_uic(uic) +{ +} + +void WriteImports::acceptUI(DomUI *node) +{ + auto &output = m_uic->output(); + output << standardImports << '\n'; + if (auto customWidgets = node->elementCustomWidgets()) { + TreeWalker::acceptCustomWidgets(customWidgets); + output << '\n'; + } +} + +QString WriteImports::qtModuleOf(const DomCustomWidget *node) const +{ + if (m_uic->customWidgetsInfo()->extends(node->elementClass(), QLatin1String("QAxWidget"))) + return QStringLiteral("QtAxContainer"); + if (const auto headerElement = node->elementHeader()) { + const auto &header = headerElement->text(); + if (header.startsWith(QLatin1String("Qt"))) { + const int slash = header.indexOf(QLatin1Char('/')); + if (slash != -1) + return header.left(slash); + } + } + return QString(); +} + +void WriteImports::acceptCustomWidget(DomCustomWidget *node) +{ + const auto &className = node->elementClass(); + if (className.contains(QLatin1String("::"))) + return; // Exclude namespaced names (just to make tests pass). + const QString &qtModule = qtModuleOf(node); + auto &output = m_uic->output(); + if (!qtModule.isEmpty()) + output << "from PySide2." << qtModule << ' '; + output << "import " << className << '\n'; +} + +} // namespace Python + +QT_END_NAMESPACE diff --git a/src/tools/uic/python/pythonwriteimports.h b/src/tools/uic/python/pythonwriteimports.h new file mode 100644 index 0000000000..427cbb48b1 --- /dev/null +++ b/src/tools/uic/python/pythonwriteimports.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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$ +** +****************************************************************************/ + +#ifndef PYTHONWRITEIMPORTS_H +#define PYTHONWRITEIMPORTS_H + +#include <treewalker.h> + +QT_BEGIN_NAMESPACE + +class Uic; + +namespace Python { + +struct WriteImports : public TreeWalker +{ +public: + explicit WriteImports(Uic *uic); + + void acceptUI(DomUI *node) override; + void acceptCustomWidget(DomCustomWidget *node) override; + +private: + QString qtModuleOf(const DomCustomWidget *node) const; + + Uic *const m_uic; +}; + +} // namespace Python + +QT_END_NAMESPACE + +#endif // PYTHONWRITEIMPORTS_H diff --git a/src/tools/uic/qclass_lib_map.h b/src/tools/uic/qclass_lib_map.h index 8e1afa0878..8cebe65a00 100644 --- a/src/tools/uic/qclass_lib_map.h +++ b/src/tools/uic/qclass_lib_map.h @@ -249,7 +249,7 @@ QT_CLASS_LIB(QLatin1String, QtCore, qstring.h) QT_CLASS_LIB(QCharRef, QtCore, qstring.h) QT_CLASS_LIB(QConstString, QtCore, qstring.h) QT_CLASS_LIB(QStringRef, QtCore, qstring.h) -QT_CLASS_LIB(QLatin1Literal, QtCore, qstringbuilder.h) +QT_CLASS_LIB(QLatin1Literal, QtCore, qstring.h) QT_CLASS_LIB(QAbstractConcatenable, QtCore, qstringbuilder.h) QT_CLASS_LIB(QConcatenable, QtCore, qstringbuilder.h) QT_CLASS_LIB(QStringBuilder, QtCore, qstringbuilder.h) diff --git a/src/tools/uic/shared/language.cpp b/src/tools/uic/shared/language.cpp index 730e1562bc..235a8ed2fc 100644 --- a/src/tools/uic/shared/language.cpp +++ b/src/tools/uic/shared/language.cpp @@ -32,6 +32,50 @@ namespace language { +static Encoding encoding = Encoding::Utf8; +static Language _language = Language::Cpp; + +Language language() { return _language; } + +void setLanguage(Language l) +{ + _language = l; + switch (_language) { + case Language::Cpp: + derefPointer = QLatin1String("->"); + nullPtr = QLatin1String("nullptr"); + operatorNew = QLatin1String("new "); + qtQualifier = QLatin1String("Qt::"); + qualifier = QLatin1String("::"); + self = QLatin1String(""); // for testing: change to "this->"; + eol = QLatin1String(";\n"); + encoding = Encoding::Utf8; + break; + case Language::Python: + derefPointer = QLatin1String("."); + nullPtr = QLatin1String("None"); + operatorNew = QLatin1String(""); + qtQualifier = QLatin1String("Qt."); + qualifier = QLatin1String("."); + self = QLatin1String("self."); + eol = QLatin1String("\n"); + encoding = Encoding::Unicode; + break; + } +} + +QString derefPointer; +QString nullPtr; +QString operatorNew; +QString qtQualifier; +QString qualifier; +QString self; +QString eol; + +QString cppQualifier = QLatin1String("::"); +QString cppTrue = QLatin1String("true"); +QString cppFalse = QLatin1String("false"); + QTextStream &operator<<(QTextStream &str, const qtConfig &c) { str << "QT_CONFIG(" << c.parameter() << ')'; @@ -69,6 +113,13 @@ const char *lookupEnum(const EnumLookup(&array)[N], int value, int defaultIndex return defaultValue; } +QString fixClassName(QString className) +{ + if (language() == Language::Python) + className.replace(cppQualifier, QLatin1String("_")); + return className; +} + const char *toolbarArea(int v) { static const EnumLookup toolBarAreas[] = @@ -141,4 +192,235 @@ const char *paletteColorRole(int v) return lookupEnum(colorRoles, v); } +// Helpers for formatting a character sequences + +// Format a special character like '\x0a' +static int formatEscapedNumber(QTextStream &str, ushort value, int base, int width, + char prefix = 0) +{ + int length = 1 + width; + str << '\\'; + if (prefix) { + str << prefix; + ++length; + } + const auto oldPadChar = str.padChar(); + const auto oldFieldWidth = str.fieldWidth(); + const auto oldFieldAlignment = str.fieldAlignment(); + const auto oldIntegerBase = str.integerBase(); + str.setPadChar(QLatin1Char('0')); + str.setFieldWidth(width); + str.setFieldAlignment(QTextStream::AlignRight); + str.setIntegerBase(base); + str << value; + str.setIntegerBase(oldIntegerBase); + str.setFieldAlignment(oldFieldAlignment); + str.setFieldWidth(oldFieldWidth); + str.setPadChar(oldPadChar); + return length; +} + +static int formatSpecialCharacter(QTextStream &str, ushort value) +{ + int length = 0; + switch (value) { + case '\\': + str << "\\\\"; + length += 2; + break; + case '\"': + str << "\\\""; + length += 2; + break; + case '\n': + str << "\\n\"\n\""; + length += 5; + break; + default: + break; + } + return length; +} + +// Format a sequence of characters for C++ with special characters numerically +// escaped (non-raw string literals), wrappped at maxSegmentSize. FormattingTraits +// are used to transform characters into (unsigned) codes, which can be used +// for either normal escapes or Unicode code points as used in Unicode literals. + +enum : int { maxSegmentSize = 1024 }; + +template <Encoding e> +struct FormattingTraits +{ +}; + +template <> +struct FormattingTraits<Encoding::Utf8> +{ + static ushort code(char c) { return uchar(c); } +}; + +template <> +struct FormattingTraits<Encoding::Unicode> +{ + static ushort code(QChar c) { return c.unicode(); } +}; + +template <Encoding e, class Iterator> +static void formatStringSequence(QTextStream &str, Iterator it, Iterator end, + const QString &indent, + int escapeIntegerBase, int escapeWidth, + char escapePrefix = 0) +{ + str << '"'; + int length = 0; + while (it != end) { + const auto code = FormattingTraits<e>::code(*it); + if (code >= 0x80) { + length += formatEscapedNumber(str, code, escapeIntegerBase, escapeWidth, escapePrefix); + } else if (const int l = formatSpecialCharacter(str, code)) { + length += l; + } else if (code != '\r') { + str << *it; + ++length; + } + ++it; + if (it != end && length > maxSegmentSize) { + str << "\"\n" << indent << indent << '"'; + length = 0; + } + } + str << '"'; +} + +void _formatString(QTextStream &str, const QString &value, const QString &indent, + bool qString) +{ + switch (encoding) { + // Special characters as 3 digit octal escapes (u8"\303\234mlaut") + case Encoding::Utf8: { + if (qString && _language == Language::Cpp) + str << "QString::fromUtf8("; + const QByteArray utf8 = value.toUtf8(); + formatStringSequence<Encoding::Utf8>(str, utf8.cbegin(), utf8.cend(), indent, + 8, 3); + if (qString && _language == Language::Cpp) + str << ')'; + } + break; + // Special characters as 4 digit hex Unicode points (u8"\u00dcmlaut") + case Encoding::Unicode: + str << 'u'; // Python Unicode literal (would be UTF-16 in C++) + formatStringSequence<Encoding::Unicode>(str, value.cbegin(), value.cend(), indent, + 16, 4, 'u'); + break; + } +} + +QTextStream &operator<<(QTextStream &str, const repeat &r) +{ + for (int i = 0; i < r.m_count; ++i) + str << r.m_char; + return str; +} + +startFunctionDefinition1::startFunctionDefinition1(const char *name, const QString ¶meterType, + const QString ¶meterName, + const QString &indent, + const char *returnType) : + m_name(name), m_parameterType(parameterType), m_parameterName(parameterName), + m_indent(indent), m_return(returnType) +{ +} + +QTextStream &operator<<(QTextStream &str, const startFunctionDefinition1 &f) +{ + switch (language()) { + case Language::Cpp: + str << (f.m_return ? f.m_return : "void") << ' ' << f.m_name << '(' + << f.m_parameterType; + if (f.m_parameterType.cend()->isLetter()) + str << ' '; + str << f.m_parameterName << ')' << '\n' << f.m_indent << "{\n"; + break; + case Language::Python: + str << "def " << f.m_name << "(self, " << f.m_parameterName << "):\n"; + break; + } + return str; +} + +endFunctionDefinition::endFunctionDefinition(const char *name) : m_name(name) +{ +} + +QTextStream &operator<<(QTextStream &str, const endFunctionDefinition &f) +{ + switch (language()) { + case Language::Cpp: + str << "} // " << f.m_name << "\n\n"; + break; + case Language::Python: + str << "# " << f.m_name << "\n\n"; + break; + } + return str; +} + +void _formatStackVariable(QTextStream &str, const char *className, QStringView varName, + bool withInitParameters) +{ + switch (language()) { + case Language::Cpp: + str << className << ' ' << varName; + if (withInitParameters) + str << '('; + break; + case Language::Python: + str << varName << " = " << className << '('; + if (!withInitParameters) + str << ')'; + break; + } +} + +void formatConnection(QTextStream &str, const SignalSlot &sender, const SignalSlot &receiver) +{ + switch (language()) { + case Language::Cpp: + str << "QObject::connect(" << sender.name << ", SIGNAL("<< sender.signature + << "), " << receiver.name << ", SLOT("<< receiver.signature << "))"; + break; + case Language::Python: + str << sender.name << '.' + << sender.signature.leftRef(sender.signature.indexOf(QLatin1Char('('))) + << ".connect(" << receiver.name << '.' + << receiver.signature.leftRef(receiver.signature.indexOf(QLatin1Char('('))) + << ')'; + break; + } +} + +QString boolValue(bool v) +{ + switch (language()) { + case Language::Cpp: + return v ? cppTrue : cppFalse; + case Language::Python: + return v ? QStringLiteral("True") : QStringLiteral("False"); + } + Q_UNREACHABLE(); +} + +static inline QString dot() { return QStringLiteral("."); } + +QString enumValue(const QString &value) +{ + if (language() == Language::Cpp || !value.contains(cppQualifier)) + return value; + QString fixed = value; + fixed.replace(cppQualifier, dot()); + return fixed; +} + } // namespace language diff --git a/src/tools/uic/shared/language.h b/src/tools/uic/shared/language.h index e7201b6529..fc8af9715b 100644 --- a/src/tools/uic/shared/language.h +++ b/src/tools/uic/shared/language.h @@ -29,12 +29,31 @@ #ifndef LANGUAGE_H #define LANGUAGE_H +#include <QtCore/qstring.h> #include <QtCore/qstringview.h> +#include <QtCore/qstring.h> QT_FORWARD_DECLARE_CLASS(QTextStream) +enum class Language { Cpp, Python }; + namespace language { +Language language(); +void setLanguage(Language); + +extern QString derefPointer; +extern QString nullPtr; +extern QString operatorNew; +extern QString qtQualifier; +extern QString qualifier; +extern QString self; +extern QString eol; + +extern QString cppQualifier; +extern QString cppTrue; +extern QString cppFalse; + // Base class for streamable objects with one QStringView parameter class StringViewStreamable { @@ -71,11 +90,119 @@ public: QTextStream &operator<<(QTextStream &, const closeQtConfig &c); +QString fixClassName(QString className); + const char *toolbarArea(int v); const char *sizePolicy(int v); const char *dockWidgetArea(int v); const char *paletteColorRole(int v); +enum class Encoding { Utf8, Unicode }; + +void _formatString(QTextStream &str, const QString &value, const QString &indent, + bool qString); + +template <bool AsQString> +class _string +{ +public: + explicit _string(const QString &value, const QString &indent = QString()) + : m_value(value), m_indent(indent) {} + + void format(QTextStream &str) const + { _formatString(str, m_value, m_indent, AsQString); } + +private: + const QString &m_value; + const QString &m_indent; +}; + +template <bool AsQString> +inline QTextStream &operator<<(QTextStream &str, const language::_string<AsQString> &s) +{ + s.format(str); + return str; +} + +using charliteral = _string<false>; +using qstring = _string<true>; + +class repeat { +public: + explicit repeat(int count, char c) : m_count(count), m_char(c) {} + + friend QTextStream &operator<<(QTextStream &str, const repeat &r); + +private: + const int m_count; + const char m_char; +}; + +class startFunctionDefinition1 { +public: + explicit startFunctionDefinition1(const char *name, const QString ¶meterType, + const QString ¶meterName, + const QString &indent, + const char *returnType = nullptr); + + friend QTextStream &operator<<(QTextStream &str, const startFunctionDefinition1 &f); +private: + const char *m_name; + const QString &m_parameterType; + const QString &m_parameterName; + const QString &m_indent; + const char *m_return; +}; + +class endFunctionDefinition { +public: + explicit endFunctionDefinition(const char *name); + + friend QTextStream &operator<<(QTextStream &str, const endFunctionDefinition &f); +private: + const char *m_name; +}; + +void _formatStackVariable(QTextStream &str, const char *className, QStringView varName, bool withInitParameters); + +template <bool withInitParameters> +class _stackVariable { +public: + explicit _stackVariable(const char *className, QStringView varName) : + m_className(className), m_varName(varName) {} + + void format(QTextStream &str) const + { _formatStackVariable(str, m_className, m_varName, withInitParameters); } + +private: + const char *m_className; + QStringView m_varName; + QStringView m_parameters; +}; + +template <bool withInitParameters> +inline QTextStream &operator<<(QTextStream &str, const _stackVariable<withInitParameters> &s) +{ + s.format(str); + return str; +} + +using stackVariable = _stackVariable<false>; +using stackVariableWithInitParameters = _stackVariable<true>; + +struct SignalSlot +{ + QString name; + QString signature; + QString className; +}; + +void formatConnection(QTextStream &str, const SignalSlot &sender, const SignalSlot &receiver); + +QString boolValue(bool v); + +QString enumValue(const QString &value); + } // namespace language #endif // LANGUAGE_H diff --git a/src/tools/uic/treewalker.h b/src/tools/uic/treewalker.h index 7e8eda57d9..3777229517 100644 --- a/src/tools/uic/treewalker.h +++ b/src/tools/uic/treewalker.h @@ -77,6 +77,9 @@ class DomButtonGroup; struct TreeWalker { + Q_DISABLE_COPY_MOVE(TreeWalker) + + TreeWalker() = default; inline virtual ~TreeWalker() = default; virtual void acceptUI(DomUI *ui); @@ -101,7 +104,7 @@ struct TreeWalker virtual void acceptTime(DomTime *time); virtual void acceptDateTime(DomDateTime *dateTime); virtual void acceptProperty(DomProperty *property); - typedef QVector<DomWidget *> DomWidgets; + using DomWidgets = QVector<DomWidget *>; virtual void acceptIncludes(DomIncludes *includes); virtual void acceptInclude(DomInclude *incl); virtual void acceptAction(DomAction *action); diff --git a/src/tools/uic/ui4.cpp b/src/tools/uic/ui4.cpp index 984ef36274..334ced276d 100644 --- a/src/tools/uic/ui4.cpp +++ b/src/tools/uic/ui4.cpp @@ -76,6 +76,10 @@ void DomUI::read(QXmlStreamReader &reader) setAttributeIdbasedtr(attribute.value() == QLatin1String("true")); continue; } + if (name == QLatin1String("connectslotsbyname")) { + setAttributeConnectslotsbyname(attribute.value() == QLatin1String("true")); + continue; + } if (name == QLatin1String("stdsetdef")) { setAttributeStdsetdef(attribute.value().toInt()); continue; @@ -209,6 +213,9 @@ void DomUI::write(QXmlStreamWriter &writer, const QString &tagName) const if (hasAttributeIdbasedtr()) writer.writeAttribute(QStringLiteral("idbasedtr"), (attributeIdbasedtr() ? QLatin1String("true") : QLatin1String("false"))); + if (hasAttributeConnectslotsbyname()) + writer.writeAttribute(QStringLiteral("connectslotsbyname"), (attributeConnectslotsbyname() ? QLatin1String("true") : QLatin1String("false"))); + if (hasAttributeStdsetdef()) writer.writeAttribute(QStringLiteral("stdsetdef"), QString::number(attributeStdsetdef())); diff --git a/src/tools/uic/ui4.h b/src/tools/uic/ui4.h index 1710147342..08a3abf490 100644 --- a/src/tools/uic/ui4.h +++ b/src/tools/uic/ui4.h @@ -169,6 +169,11 @@ public: inline void setAttributeIdbasedtr(bool a) { m_attr_idbasedtr = a; m_has_attr_idbasedtr = true; } inline void clearAttributeIdbasedtr() { m_has_attr_idbasedtr = false; } + inline bool hasAttributeConnectslotsbyname() const { return m_has_attr_connectslotsbyname; } + inline bool attributeConnectslotsbyname() const { return m_attr_connectslotsbyname; } + inline void setAttributeConnectslotsbyname(bool a) { m_attr_connectslotsbyname = a; m_has_attr_connectslotsbyname = true; } + inline void clearAttributeConnectslotsbyname() { m_has_attr_connectslotsbyname = false; } + inline bool hasAttributeStdsetdef() const { return m_has_attr_stdsetdef; } inline int attributeStdsetdef() const { return m_attr_stdsetdef; } inline void setAttributeStdsetdef(int a) { m_attr_stdsetdef = a; m_has_attr_stdsetdef = true; } @@ -285,6 +290,9 @@ private: bool m_attr_idbasedtr = false; bool m_has_attr_idbasedtr = false; + bool m_attr_connectslotsbyname = false; + bool m_has_attr_connectslotsbyname = false; + int m_attr_stdsetdef = 0; bool m_has_attr_stdsetdef = false; diff --git a/src/tools/uic/uic.cpp b/src/tools/uic/uic.cpp index 225dc6aeb2..207356f28d 100644 --- a/src/tools/uic/uic.cpp +++ b/src/tools/uic/uic.cpp @@ -35,6 +35,10 @@ #include "cppwriteincludes.h" #include "cppwritedeclaration.h" +#include <pythonwritedeclaration.h> +#include <pythonwriteimports.h> + +#include <language.h> #include <qxmlstream.h> #include <qfileinfo.h> @@ -65,7 +69,7 @@ bool Uic::printDependencies() return false; } - DomUI *ui = 0; + DomUI *ui = nullptr; { QXmlStreamReader reader; reader.setDevice(&f); @@ -103,7 +107,7 @@ bool Uic::printDependencies() return true; } -void Uic::writeCopyrightHeader(DomUI *ui) +void Uic::writeCopyrightHeaderCpp(const DomUI *ui) const { QString comment = ui->elementComment(); if (!comment.isEmpty()) @@ -118,6 +122,48 @@ void Uic::writeCopyrightHeader(DomUI *ui) out << "********************************************************************************/\n\n"; } +// Format existing UI file comments for Python with some smartness : Replace all +// leading C++ comment characters by '#' or prepend '#' if needed. + +static inline bool isCppCommentChar(QChar c) +{ + return c == QLatin1Char('/') || c == QLatin1Char('*'); +} + +static int leadingCppCommentCharCount(const QStringRef &s) +{ + int i = 0; + for (const int size = s.size(); i < size && isCppCommentChar(s.at(i)); ++i) { + } + return i; +} + +void Uic::writeCopyrightHeaderPython(const DomUI *ui) const +{ + QString comment = ui->elementComment(); + if (!comment.isEmpty()) { + const auto lines = comment.splitRef(QLatin1Char('\n')); + for (const auto &line : lines) { + if (const int leadingCommentChars = leadingCppCommentCharCount(line)) { + out << language::repeat(leadingCommentChars, '#') + << line.right(line.size() - leadingCommentChars); + } else { + if (!line.startsWith(QLatin1Char('#'))) + out << "# "; + out << line; + } + out << '\n'; + } + out << '\n'; + } + + out << language::repeat(80, '#') << "\n## Form generated from reading UI file '" + << QFileInfo(opt.inputFile).fileName() + << "'\n##\n## Created by: Qt User Interface Compiler version " << QT_VERSION_STR + << "\n##\n## WARNING! All changes made in this file will be lost when recompiling UI file!\n" + << language::repeat(80, '#') << "\n\n"; +} + // Check the version with a stream reader at the <ui> element. static double versionFromUiAttribute(QXmlStreamReader &reader) @@ -132,7 +178,7 @@ static double versionFromUiAttribute(QXmlStreamReader &reader) DomUI *Uic::parseUiFile(QXmlStreamReader &reader) { - DomUI *ui = 0; + DomUI *ui = nullptr; const QString uiElement = QLatin1String("ui"); while (!reader.atEnd()) { @@ -143,7 +189,7 @@ DomUI *Uic::parseUiFile(QXmlStreamReader &reader) if (version < 4.0) { const QString msg = QString::fromLatin1("uic: File generated with too old version of Qt Designer (%1)").arg(version); fprintf(stderr, "%s\n", qPrintable(msg)); - return 0; + return nullptr; } ui = new DomUI(); @@ -155,7 +201,7 @@ DomUI *Uic::parseUiFile(QXmlStreamReader &reader) } if (reader.hasError()) { delete ui; - ui = 0; + ui = nullptr; fprintf(stderr, "%s\n", qPrintable(QString::fromLatin1("uic: Error in line %1, column %2 : %3") .arg(reader.lineNumber()).arg(reader.columnNumber()) .arg(reader.errorString()))); @@ -195,15 +241,26 @@ bool Uic::write(QIODevice *in) bool Uic::write(DomUI *ui) { - using namespace CPP; - if (!ui || !ui->elementWidget()) return false; - if (opt.copyrightHeader) - writeCopyrightHeader(ui); + const auto lang = language::language(); + + if (lang == Language::Python) + out << "# -*- coding: utf-8 -*-\n\n"; - if (opt.headerProtection) { + if (opt.copyrightHeader) { + switch (language::language()) { + case Language::Cpp: + writeCopyrightHeaderCpp(ui); + break; + case Language::Python: + writeCopyrightHeaderPython(ui); + break; + } + } + + if (opt.headerProtection && lang == Language::Cpp) { writeHeaderProtectionStart(); out << "\n"; } @@ -218,13 +275,25 @@ bool Uic::write(DomUI *ui) info.acceptUI(ui); cWidgetsInfo.acceptUI(ui); - WriteIncludes writeIncludes(this); - writeIncludes.acceptUI(ui); - Validator(this).acceptUI(ui); - WriteDeclaration(this).acceptUI(ui); + switch (language::language()) { + case Language::Cpp: { + CPP::WriteIncludes writeIncludes(this); + writeIncludes.acceptUI(ui); + Validator(this).acceptUI(ui); + CPP::WriteDeclaration(this).acceptUI(ui); + } + break; + case Language::Python: { + Python::WriteImports writeImports(this); + writeImports.acceptUI(ui); + Validator(this).acceptUI(ui); + Python::WriteDeclaration(this).acceptUI(ui); + } + break; + } - if (opt.headerProtection) + if (opt.headerProtection && lang == Language::Cpp) writeHeaderProtectionEnd(); return true; diff --git a/src/tools/uic/uic.h b/src/tools/uic/uic.h index af5f42c6db..f3dfd49149 100644 --- a/src/tools/uic/uic.h +++ b/src/tools/uic/uic.h @@ -91,7 +91,8 @@ public: private: // copyright header - void writeCopyrightHeader(DomUI *ui); + void writeCopyrightHeaderCpp(const DomUI *ui) const; + void writeCopyrightHeaderPython(const DomUI *ui) const; DomUI *parseUiFile(QXmlStreamReader &reader); // header protection diff --git a/src/tools/uic/uic.pro b/src/tools/uic/uic.pro index 4469ce50e5..1bf8ef8ad3 100644 --- a/src/tools/uic/uic.pro +++ b/src/tools/uic/uic.pro @@ -7,6 +7,7 @@ DEFINES += QT_UIC QT_NO_CAST_FROM_ASCII QT_NO_FOREACH include(uic.pri) include(shared/shared.pri) include(cpp/cpp.pri) +include(python/python.pri) HEADERS += uic.h diff --git a/src/tools/uic/utils.h b/src/tools/uic/utils.h index 3f32a532ca..34c4ab23d4 100644 --- a/src/tools/uic/utils.h +++ b/src/tools/uic/utils.h @@ -42,55 +42,6 @@ inline bool toBool(const QString &str) inline QString toString(const DomString *str) { return str ? str->text() : QString(); } -inline QString fixString(const QString &str, const QString &indent) -{ - QString cursegment; - QStringList result; - const QByteArray utf8 = str.toUtf8(); - const int utf8Length = utf8.length(); - - for (int i = 0; i < utf8Length; ++i) { - const uchar cbyte = utf8.at(i); - if (cbyte >= 0x80) { - cursegment += QLatin1Char('\\'); - cursegment += QString::number(cbyte, 8); - } else { - switch(cbyte) { - case '\\': - cursegment += QLatin1String("\\\\"); break; - case '\"': - cursegment += QLatin1String("\\\""); break; - case '\r': - break; - case '\n': - cursegment += QLatin1String("\\n\"\n\""); break; - default: - cursegment += QLatin1Char(cbyte); - } - } - - if (cursegment.length() > 1024) { - result << cursegment; - cursegment.clear(); - } - } - - if (!cursegment.isEmpty()) - result << cursegment; - - - QString joinstr = QLatin1String("\"\n"); - joinstr += indent; - joinstr += indent; - joinstr += QLatin1Char('"'); - - QString rc(QLatin1Char('"')); - rc += result.join(joinstr); - rc += QLatin1Char('"'); - - return rc; -} - inline QHash<QString, DomProperty *> propertyMap(const QList<DomProperty *> &properties) { QHash<QString, DomProperty *> map; |