diff options
Diffstat (limited to 'src/tools/uic/shared/language.cpp')
-rw-r--r-- | src/tools/uic/shared/language.cpp | 254 |
1 files changed, 139 insertions, 115 deletions
diff --git a/src/tools/uic/shared/language.cpp b/src/tools/uic/shared/language.cpp index 2f2ae3ebc6..d59688e346 100644 --- a/src/tools/uic/shared/language.cpp +++ b/src/tools/uic/shared/language.cpp @@ -1,37 +1,15 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "language.h" #include <QtCore/qtextstream.h> +#include <QtCore/QList> namespace language { +using namespace Qt::StringLiterals; + static Encoding encoding = Encoding::Utf8; static Language _language = Language::Cpp; @@ -42,29 +20,29 @@ void setLanguage(Language l) _language = l; switch (_language) { case Language::Cpp: - derefPointer = QLatin1String("->"); + derefPointer = u"->"_s; listStart = '{'; listEnd = '}'; - nullPtr = QLatin1String("nullptr"); - operatorNew = QLatin1String("new "); - qtQualifier = QLatin1String("Qt::"); - qualifier = QLatin1String("::"); - self = QLatin1String(""); // for testing: change to "this->"; - eol = QLatin1String(";\n"); - emptyString = QLatin1String("QString()"); + nullPtr = u"nullptr"_s; + operatorNew = u"new "_s; + qtQualifier = u"Qt::"_s; + qualifier = u"::"_s; + self = u""_s; // for testing: change to "this->"; + eol = u";\n"_s; + emptyString = u"QString()"_s; encoding = Encoding::Utf8; break; case Language::Python: - derefPointer = QLatin1String("."); + derefPointer = u"."_s; listStart = '['; listEnd = ']'; - nullPtr = QLatin1String("None"); - operatorNew = QLatin1String(""); - qtQualifier = QLatin1String("Qt."); - qualifier = QLatin1String("."); - self = QLatin1String("self."); - eol = QLatin1String("\n"); - emptyString = QLatin1String("\"\""); + nullPtr = u"None"_s; + operatorNew = u""_s; + qtQualifier = u"Qt."_s; + qualifier = u"."_s; + self = u"self."_s; + eol = u"\n"_s; + emptyString = u"\"\""_s; encoding = Encoding::Unicode; break; } @@ -81,9 +59,9 @@ QString self; QString eol; QString emptyString; -QString cppQualifier = QLatin1String("::"); -QString cppTrue = QLatin1String("true"); -QString cppFalse = QLatin1String("false"); +QString cppQualifier = u"::"_s; +QString cppTrue = u"true"_s; +QString cppFalse = u"false"_s; QTextStream &operator<<(QTextStream &str, const qtConfig &c) { @@ -106,97 +84,97 @@ QTextStream &operator<<(QTextStream &str, const closeQtConfig &c) struct EnumLookup { int value; - const char *valueString; + QLatin1StringView valueString; }; template <int N> -const char *lookupEnum(const EnumLookup(&array)[N], int value, int defaultIndex = 0) +QLatin1StringView lookupEnum(const EnumLookup(&array)[N], int value, int defaultIndex = 0) { for (int i = 0; i < N; ++i) { if (value == array[i].value) return array[i].valueString; } - const char *defaultValue = array[defaultIndex].valueString; + auto defaultValue = array[defaultIndex].valueString; qWarning("uic: Warning: Invalid enumeration value %d, defaulting to %s", - value, defaultValue); + value, defaultValue.data()); return defaultValue; } QString fixClassName(QString className) { if (language() == Language::Python) - className.replace(cppQualifier, QLatin1String("_")); + className.replace(cppQualifier, "_"_L1); return className; } -const char *toolbarArea(int v) +QLatin1StringView toolbarArea(int v) { static const EnumLookup toolBarAreas[] = { - {0, "NoToolBarArea"}, - {0x1, "LeftToolBarArea"}, - {0x2, "RightToolBarArea"}, - {0x4, "TopToolBarArea"}, - {0x8, "BottomToolBarArea"}, - {0xf, "AllToolBarAreas"} + {0, "NoToolBarArea"_L1}, + {0x1, "LeftToolBarArea"_L1}, + {0x2, "RightToolBarArea"_L1}, + {0x4, "TopToolBarArea"_L1}, + {0x8, "BottomToolBarArea"_L1}, + {0xf, "AllToolBarAreas"_L1} }; return lookupEnum(toolBarAreas, v); } -const char *sizePolicy(int v) +QLatin1StringView sizePolicy(int v) { static const EnumLookup sizePolicies[] = { - {0, "Fixed"}, - {0x1, "Minimum"}, - {0x4, "Maximum"}, - {0x5, "Preferred"}, - {0x3, "MinimumExpanding"}, - {0x7, "Expanding"}, - {0xD, "Ignored"} + {0, "Fixed"_L1}, + {0x1, "Minimum"_L1}, + {0x4, "Maximum"_L1}, + {0x5, "Preferred"_L1}, + {0x3, "MinimumExpanding"_L1}, + {0x7, "Expanding"_L1}, + {0xD, "Ignored"_L1} }; return lookupEnum(sizePolicies, v, 3); } -const char *dockWidgetArea(int v) +QLatin1StringView dockWidgetArea(int v) { static const EnumLookup dockWidgetAreas[] = { - {0, "NoDockWidgetArea"}, - {0x1, "LeftDockWidgetArea"}, - {0x2, "RightDockWidgetArea"}, - {0x4, "TopDockWidgetArea"}, - {0x8, "BottomDockWidgetArea"}, - {0xf, "AllDockWidgetAreas"} + {0, "NoDockWidgetArea"_L1}, + {0x1, "LeftDockWidgetArea"_L1}, + {0x2, "RightDockWidgetArea"_L1}, + {0x4, "TopDockWidgetArea"_L1}, + {0x8, "BottomDockWidgetArea"_L1}, + {0xf, "AllDockWidgetAreas"_L1} }; return lookupEnum(dockWidgetAreas, v); } -const char *paletteColorRole(int v) +QLatin1StringView paletteColorRole(int v) { static const EnumLookup colorRoles[] = { - {0, "WindowText"}, - {1, "Button"}, - {2, "Light"}, - {3, "Midlight"}, - {4, "Dark"}, - {5, "Mid"}, - {6, "Text"}, - {7, "BrightText"}, - {8, "ButtonText"}, - {9, "Base"}, - {10, "Window"}, - {11, "Shadow"}, - {12, "Highlight"}, - {13, "HighlightedText"}, - {14, "Link"}, - {15, "LinkVisited"}, - {16, "AlternateBase"}, - {17, "NoRole"}, - {18, "ToolTipBase"}, - {19, "ToolTipText"}, - {20, "PlaceholderText"}, + {0, "WindowText"_L1}, + {1, "Button"_L1}, + {2, "Light"_L1}, + {3, "Midlight"_L1}, + {4, "Dark"_L1}, + {5, "Mid"_L1}, + {6, "Text"_L1}, + {7, "BrightText"_L1}, + {8, "ButtonText"_L1}, + {9, "Base"_L1}, + {10, "Window"_L1}, + {11, "Shadow"_L1}, + {12, "Highlight"_L1}, + {13, "HighlightedText"_L1}, + {14, "Link"_L1}, + {15, "LinkVisited"_L1}, + {16, "AlternateBase"_L1}, + {17, "NoRole"_L1}, + {18, "ToolTipBase"_L1}, + {19, "ToolTipText"_L1}, + {20, "PlaceholderText"_L1}, }; return lookupEnum(colorRoles, v); } @@ -217,7 +195,7 @@ static int formatEscapedNumber(QTextStream &str, ushort value, int base, int wid const auto oldFieldWidth = str.fieldWidth(); const auto oldFieldAlignment = str.fieldAlignment(); const auto oldIntegerBase = str.integerBase(); - str.setPadChar(QLatin1Char('0')); + str.setPadChar(u'0'); str.setFieldWidth(width); str.setFieldAlignment(QTextStream::AlignRight); str.setIntegerBase(base); @@ -393,29 +371,65 @@ void _formatStackVariable(QTextStream &str, const char *className, QStringView v } } -enum OverloadUse { - UseOverload, - UseOverloadWhenNoArguments, // Use overload only when the argument list is empty, - // in this case there is no chance of connecting - // mismatching T against const T & - DontUseOverload +enum class OverloadUse { + Always, + WhenAmbiguousOrEmpty, // Use overload if + // - signal/slot is ambiguous + // - argument list is empty (chance of connecting mismatching T against const T &) + Never, }; // Format a member function for a signal slot connection -static void formatMemberFnPtr(QTextStream &str, const SignalSlot &s, - OverloadUse useQOverload = DontUseOverload) +static bool isConstRef(const QStringView &arg) { - const int parenPos = s.signature.indexOf(QLatin1Char('(')); + return arg.startsWith(u'Q') && arg != "QPoint"_L1 && arg != "QSize"_L1; +} + +static QString formatOverload(const QStringView ¶meters) +{ + QString result = "qOverload<"_L1; + const auto args = QStringView{parameters}.split(u','); + for (qsizetype i = 0, size = args.size(); i < size; ++i) { + const auto &arg = args.at(i); + if (i > 0) + result += u','; + const bool constRef = isConstRef(arg); + if (constRef) + result += "const "_L1; + result += arg; + if (constRef) + result += u'&'; + } + result += u'>'; + return result; +} + +static void formatMemberFnPtr(QTextStream &str, const SignalSlot &s, OverloadUse useQOverload) +{ + const qsizetype parenPos = s.signature.indexOf(u'('); Q_ASSERT(parenPos >= 0); const auto functionName = QStringView{s.signature}.left(parenPos); const auto parameters = QStringView{s.signature}.mid(parenPos + 1, s.signature.size() - parenPos - 2); - const bool withOverload = useQOverload == UseOverload || - (useQOverload == UseOverloadWhenNoArguments && parameters.isEmpty()); + + const bool isAmbiguous = s.options.testFlag(SignalSlotOption::Ambiguous); + bool withOverload = false; // just to silence the compiler + + switch (useQOverload) { + case OverloadUse::Always: + withOverload = true; + break; + case OverloadUse::Never: + withOverload = false; + break; + case OverloadUse::WhenAmbiguousOrEmpty: + withOverload = parameters.empty() || isAmbiguous; + break; + } if (withOverload) - str << "qOverload<" << parameters << ">("; + str << formatOverload(parameters) << '('; str << '&' << s.className << "::" << functionName; @@ -428,9 +442,9 @@ static void formatMemberFnPtrConnection(QTextStream &str, const SignalSlot &receiver) { str << "QObject::connect(" << sender.name << ", "; - formatMemberFnPtr(str, sender); + formatMemberFnPtr(str, sender, OverloadUse::Never); str << ", " << receiver.name << ", "; - formatMemberFnPtr(str, receiver, UseOverloadWhenNoArguments); + formatMemberFnPtr(str, receiver, OverloadUse::WhenAmbiguousOrEmpty); str << ')'; } @@ -456,12 +470,22 @@ void formatConnection(QTextStream &str, const SignalSlot &sender, const SignalSl break; } break; - case Language::Python: - str << sender.name << '.' - << QStringView{sender.signature}.left(sender.signature.indexOf(QLatin1Char('('))) - << ".connect(" << receiver.name << '.' - << QStringView{receiver.signature}.left(receiver.signature.indexOf(QLatin1Char('('))) + case Language::Python: { + const auto paren = sender.signature.indexOf(u'('); + auto senderSignature = QStringView{sender.signature}; + str << sender.name << '.' << senderSignature.left(paren); + // Signals like "QAbstractButton::clicked(checked=false)" require + // the parameter if it is used. + if (sender.options.testFlag(SignalSlotOption::Ambiguous)) { + const QStringView parameters = + senderSignature.mid(paren + 1, senderSignature.size() - paren - 2); + if (!parameters.isEmpty() && !parameters.contains(u',')) + str << "[\"" << parameters << "\"]"; + } + str << ".connect(" << receiver.name << '.' + << QStringView{receiver.signature}.left(receiver.signature.indexOf(u'(')) << ')'; + } break; } } |