summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2020-04-19 11:23:55 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2020-05-04 08:12:33 +0200
commitda3cb1deb6c752f8e4c05434e3451432e5d787ba (patch)
treec2f7992eeee39617102cb864f798ebd7c06ec5f0 /src
parent8231614661e1eecaabcf33d1e332809556e86089 (diff)
uic: Generate Qt 5 connection syntax
Add a enum and formatting for member function pointer based connections. Now preferably use member function pointer for Qt classes or parameterless connections. This should not require qOverload() within Qt classes after the Signal/Slot disambiguation. Add command line option to force either syntax for all connections. Task-number: QTBUG-76375 Change-Id: Icdb4051e1173172a71cd536bdbc7d1ab1edf267d Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/tools/uic/cpp/cppwriteincludes.cpp3
-rw-r--r--src/tools/uic/cpp/cppwriteinitialization.cpp33
-rw-r--r--src/tools/uic/cpp/cppwriteinitialization.h6
-rw-r--r--src/tools/uic/main.cpp12
-rw-r--r--src/tools/uic/option.h4
-rw-r--r--src/tools/uic/shared/language.cpp51
-rw-r--r--src/tools/uic/shared/language.h8
7 files changed, 110 insertions, 7 deletions
diff --git a/src/tools/uic/cpp/cppwriteincludes.cpp b/src/tools/uic/cpp/cppwriteincludes.cpp
index f2e69553c6..b9190b8295 100644
--- a/src/tools/uic/cpp/cppwriteincludes.cpp
+++ b/src/tools/uic/cpp/cppwriteincludes.cpp
@@ -229,6 +229,9 @@ void WriteIncludes::add(const QString &className, bool determineHeader, const QS
return;
}
+ if (cwi->extends(className, QLatin1String("QDialogButtonBox")))
+ add(QLatin1String("QAbstractButton")); // for signal "clicked(QAbstractButton*)"
+
if (determineHeader)
insertIncludeForClass(className, header, global);
}
diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp
index 2a9efaac95..585313f5de 100644
--- a/src/tools/uic/cpp/cppwriteinitialization.cpp
+++ b/src/tools/uic/cpp/cppwriteinitialization.cpp
@@ -2568,6 +2568,31 @@ WriteInitialization::Declaration WriteInitialization::findDeclaration(const QStr
return {};
}
+bool WriteInitialization::isCustomWidget(const QString &className) const
+{
+ return m_uic->customWidgetsInfo()->customWidget(className) != nullptr;
+}
+
+ConnectionSyntax WriteInitialization::connectionSyntax(const QString &senderSignature,
+ const QString &senderClassName,
+ const QString &receiverClassName) const
+{
+ if (m_option.forceMemberFnPtrConnectionSyntax)
+ return ConnectionSyntax::MemberFunctionPtr;
+ if (m_option.forceStringConnectionSyntax)
+ return ConnectionSyntax::StringBased;
+ // Auto mode: Use Qt 5 connection syntax for Qt classes and parameterless
+ // connections. QAxWidget is special though since it has a fake Meta object.
+ static const QStringList requiresStringSyntax{QStringLiteral("QAxWidget")};
+ if (requiresStringSyntax.contains(senderClassName)
+ || requiresStringSyntax.contains(receiverClassName)) {
+ return ConnectionSyntax::StringBased;
+ }
+ return senderSignature.endsWith(QLatin1String("()"))
+ || (!isCustomWidget(senderClassName) && !isCustomWidget(receiverClassName))
+ ? ConnectionSyntax::MemberFunctionPtr : ConnectionSyntax::StringBased;
+}
+
void WriteInitialization::acceptConnection(DomConnection *connection)
{
const QString senderName = connection->elementSender();
@@ -2584,14 +2609,16 @@ void WriteInitialization::acceptConnection(DomConnection *connection)
fprintf(stderr, "%s\n", qPrintable(message));
return;
}
-
- language::SignalSlot theSignal{senderDecl.name, connection->elementSignal(),
+ const QString senderSignature = connection->elementSignal();
+ language::SignalSlot theSignal{senderDecl.name, senderSignature,
senderDecl.className};
language::SignalSlot theSlot{receiverDecl.name, connection->elementSlot(),
receiverDecl.className};
m_output << m_indent;
- language::formatConnection(m_output, theSignal, theSlot);
+ language::formatConnection(m_output, theSignal, theSlot,
+ connectionSyntax(senderSignature, senderDecl.className,
+ receiverDecl.className));
m_output << language::eol;
}
diff --git a/src/tools/uic/cpp/cppwriteinitialization.h b/src/tools/uic/cpp/cppwriteinitialization.h
index 0a6ddbb3c8..df06358077 100644
--- a/src/tools/uic/cpp/cppwriteinitialization.h
+++ b/src/tools/uic/cpp/cppwriteinitialization.h
@@ -37,6 +37,8 @@
#include <qstack.h>
#include <qtextstream.h>
+enum class ConnectionSyntax;
+
QT_BEGIN_NAMESPACE
class Driver;
@@ -238,6 +240,10 @@ private:
QString writeBrushInitialization(const DomBrush *brush);
void addButtonGroup(const DomWidget *node, const QString &varName);
void addWizardPage(const QString &pageVarName, const DomWidget *page, const QString &parentWidget);
+ bool isCustomWidget(const QString &className) const;
+ ConnectionSyntax connectionSyntax(const QString &senderSignature,
+ const QString &senderClassName,
+ const QString &receiverClassName) const;
const Uic *m_uic;
Driver *m_driver;
diff --git a/src/tools/uic/main.cpp b/src/tools/uic/main.cpp
index 6f342fb398..81492bbf45 100644
--- a/src/tools/uic/main.cpp
+++ b/src/tools/uic/main.cpp
@@ -100,6 +100,11 @@ int runUic(int argc, char *argv[])
generatorOption.setValueName(QStringLiteral("python|cpp"));
parser.addOption(generatorOption);
+ QCommandLineOption connectionsOption(QStringList{QStringLiteral("c"), QStringLiteral("connections")});
+ connectionsOption.setDescription(QStringLiteral("Connection syntax."));
+ connectionsOption.setValueName(QStringLiteral("pmf|string"));
+ parser.addOption(connectionsOption);
+
QCommandLineOption idBasedOption(QStringLiteral("idbased"));
idBasedOption.setDescription(QStringLiteral("Use id based function for i18n"));
parser.addOption(idBasedOption);
@@ -122,6 +127,13 @@ int runUic(int argc, char *argv[])
driver.option().postfix = parser.value(postfixOption);
driver.option().translateFunction = parser.value(translateOption);
driver.option().includeFile = parser.value(includeOption);
+ if (parser.isSet(connectionsOption)) {
+ const auto value = parser.value(connectionsOption);
+ if (value == QLatin1String("pmf"))
+ driver.option().forceMemberFnPtrConnectionSyntax = 1;
+ else if (value == QLatin1String("string"))
+ driver.option().forceStringConnectionSyntax = 1;
+ }
Language language = Language::Cpp;
if (parser.isSet(generatorOption)) {
diff --git a/src/tools/uic/option.h b/src/tools/uic/option.h
index 8e882079c9..c869fec9a6 100644
--- a/src/tools/uic/option.h
+++ b/src/tools/uic/option.h
@@ -46,6 +46,8 @@ struct Option
unsigned int implicitIncludes: 1;
unsigned int idBased: 1;
unsigned int fromImports: 1;
+ unsigned int forceMemberFnPtrConnectionSyntax: 1;
+ unsigned int forceStringConnectionSyntax: 1;
QString inputFile;
QString outputFile;
@@ -67,6 +69,8 @@ struct Option
implicitIncludes(1),
idBased(0),
fromImports(0),
+ forceMemberFnPtrConnectionSyntax(0),
+ forceStringConnectionSyntax(0),
prefix(QLatin1String("Ui_"))
{ indent.fill(QLatin1Char(' '), 4); }
diff --git a/src/tools/uic/shared/language.cpp b/src/tools/uic/shared/language.cpp
index 987d51e30c..a42e7b8461 100644
--- a/src/tools/uic/shared/language.cpp
+++ b/src/tools/uic/shared/language.cpp
@@ -387,12 +387,57 @@ void _formatStackVariable(QTextStream &str, const char *className, QStringView v
}
}
-void formatConnection(QTextStream &str, const SignalSlot &sender, const SignalSlot &receiver)
+// Format a member function for a signal slot connection
+static void formatMemberFnPtr(QTextStream &str, const SignalSlot &s,
+ bool useQOverload = false)
+{
+ const int parenPos = s.signature.indexOf(QLatin1Char('('));
+ Q_ASSERT(parenPos >= 0);
+ if (useQOverload) {
+ const auto parameters = s.signature.midRef(parenPos + 1,
+ s.signature.size() - parenPos - 2);
+ str << "qOverload<" << parameters << ">(";
+ }
+
+ const auto functionName = s.signature.leftRef(parenPos);
+ str << '&' << s.className << "::" << functionName;
+
+ if (useQOverload)
+ str << ')';
+}
+
+static void formatMemberFnPtrConnection(QTextStream &str,
+ const SignalSlot &sender,
+ const SignalSlot &receiver)
+{
+ str << "QObject::connect(" << sender.name << ", ";
+ formatMemberFnPtr(str, sender);
+ str << ", " << receiver.name << ", ";
+ formatMemberFnPtr(str, receiver);
+ str << ')';
+}
+
+static void formatStringBasedConnection(QTextStream &str,
+ const SignalSlot &sender,
+ const SignalSlot &receiver)
+{
+ str << "QObject::connect(" << sender.name << ", SIGNAL("<< sender.signature
+ << "), " << receiver.name << ", SLOT(" << receiver.signature << "))";
+}
+
+void formatConnection(QTextStream &str, const SignalSlot &sender, const SignalSlot &receiver,
+ ConnectionSyntax connectionSyntax)
{
switch (language()) {
case Language::Cpp:
- str << "QObject::connect(" << sender.name << ", SIGNAL("<< sender.signature
- << "), " << receiver.name << ", SLOT("<< receiver.signature << "))";
+ switch (connectionSyntax) {
+ case ConnectionSyntax::MemberFunctionPtr:
+ formatMemberFnPtrConnection(str, sender, receiver);
+ break;
+ case ConnectionSyntax::StringBased:
+ formatStringBasedConnection(str, sender, receiver);
+ break;
+ }
break;
case Language::Python:
str << sender.name << '.'
diff --git a/src/tools/uic/shared/language.h b/src/tools/uic/shared/language.h
index 7b019ec8fc..fcc2d5d258 100644
--- a/src/tools/uic/shared/language.h
+++ b/src/tools/uic/shared/language.h
@@ -37,11 +37,16 @@ QT_FORWARD_DECLARE_CLASS(QTextStream)
enum class Language { Cpp, Python };
+enum class ConnectionSyntax { StringBased, MemberFunctionPtr };
+
namespace language {
Language language();
void setLanguage(Language);
+ConnectionSyntax connectionSyntax();
+void setConnectionSyntax(ConnectionSyntax cs);
+
extern QString derefPointer;
extern QString nullPtr;
extern QString operatorNew;
@@ -198,7 +203,8 @@ struct SignalSlot
QString className;
};
-void formatConnection(QTextStream &str, const SignalSlot &sender, const SignalSlot &receiver);
+void formatConnection(QTextStream &str, const SignalSlot &sender, const SignalSlot &receiver,
+ ConnectionSyntax connectionSyntax);
QString boolValue(bool v);