diff options
Diffstat (limited to 'src/tools')
56 files changed, 2922 insertions, 1551 deletions
diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp index 01c392f8f9..10bbd59bfb 100644 --- a/src/tools/androiddeployqt/main.cpp +++ b/src/tools/androiddeployqt/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** 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. @@ -52,6 +52,21 @@ #define QT_POPEN_READ "r" #endif +class ActionTimer +{ + qint64 started; +public: + ActionTimer() = default; + void start() + { + started = QDateTime::currentMSecsSinceEpoch(); + } + int elapsed() + { + return int(QDateTime::currentMSecsSinceEpoch() - started); + } +}; + static const bool mustReadOutputAnyway = true; // pclose seems to return the wrong error code unless we read the output void deleteRecursively(const QString &dirName) @@ -103,7 +118,6 @@ struct Options , timing(false) , generateAssetsFileList(true) , build(true) - , gradle(false) , auxMode(false) , deploymentMechanism(Bundled) , releasePackage(false) @@ -135,16 +149,14 @@ struct Options bool timing; bool generateAssetsFileList; bool build; - bool gradle; bool auxMode; bool stripLibraries = true; - QTime timer; + ActionTimer timer; // External tools QString sdkPath; QString sdkBuildToolsVersion; QString ndkPath; - QString antTool; QString jdkPath; // Build paths @@ -197,6 +209,7 @@ struct Options bool sectionsOnly; bool protectedAuthenticationPath; bool jarSigner; + QString apkPath; // Gdbserver TriState gdbServer; @@ -354,13 +367,6 @@ Options parseOptions() options.helpRequested = true; } else if (argument.compare(QLatin1String("--verbose"), Qt::CaseInsensitive) == 0) { options.verbose = true; - } else if (argument.compare(QLatin1String("--gradle"), Qt::CaseInsensitive) == 0) { - options.gradle = true; - } else if (argument.compare(QLatin1String("--ant"), Qt::CaseInsensitive) == 0) { - if (i + 1 == arguments.size()) - options.helpRequested = true; - else - options.antTool = arguments.at(++i); } else if (argument.compare(QLatin1String("--deployment"), Qt::CaseInsensitive) == 0) { if (i + 1 == arguments.size()) { options.helpRequested = true; @@ -391,6 +397,11 @@ Options parseOptions() options.helpRequested = true; else options.jdkPath = arguments.at(++i); + } else if (argument.compare(QLatin1String("--apk"), Qt::CaseInsensitive) == 0) { + if (i + 1 == arguments.size()) + options.helpRequested = true; + else + options.apkPath = arguments.at(++i); } else if (argument.compare(QLatin1String("--sign"), Qt::CaseInsensitive) == 0) { if (i + 2 >= arguments.size()) { options.helpRequested = true; @@ -500,9 +511,6 @@ void printHelp() " --android-platform <platform>: Builds against the given android\n" " platform. By default, the highest available version will be\n" " used.\n" - " --gradle. Use gradle instead of ant to create and install the apk.\n" - " --ant <path/to/ant>: If unspecified, ant from the PATH will be\n" - " used.\n" " --release: Builds a package ready for release. By default, the\n" " package will be signed with a debug key.\n" " --sign <url/to/keystore> <alias>: Signs the package with the\n" @@ -542,6 +550,7 @@ void printHelp() " dependencies into the build directory and update the XML templates.\n" " The project will not be built or installed.\n" " --no-strip: Do not strip debug symbols from libraries.\n" + " --apk <path/where/to/copy/the/apk>: Path where to copy the built apk.\n" " --help: Displays this information.\n\n", qPrintable(QCoreApplication::arguments().at(0)) ); @@ -1009,16 +1018,13 @@ bool copyAndroidTemplate(const Options &options) if (options.verbose) fprintf(stdout, "Copying Android package template.\n"); - if (options.gradle && !copyGradleTemplate(options)) + if (!copyGradleTemplate(options)) return false; if (!copyAndroidTemplate(options, QLatin1String("/src/android/templates"))) return false; - if (options.gradle) - return true; - - return copyAndroidTemplate(options, QLatin1String("/src/android/java")); + return true; } bool copyAndroidSources(const Options &options) @@ -1270,36 +1276,6 @@ bool updateStringsXml(const Options &options) if (!updateFile(fileName, replacements)) return false; - if (options.gradle) - return true; - - // ant can't (easily) build multiple res folders, - // so we need to replace the "<!-- %%INSERT_STRINGS -->" placeholder - // from the main res folder - QFile stringsXml(fileName); - if (!stringsXml.open(QIODevice::ReadOnly)) { - fprintf(stderr, "Cannot open %s for reading.\n", qPrintable(fileName)); - return false; - } - - QXmlStreamReader reader(&stringsXml); - while (!reader.atEnd()) { - reader.readNext(); - if (reader.isStartElement() && - reader.name() == QLatin1String("string") && - reader.attributes().hasAttribute(QLatin1String("name")) && - reader.attributes().value(QLatin1String("name")) == QLatin1String("app_name")) { - return true; - } - } - - replacements.clear(); - replacements[QStringLiteral("<!-- %%INSERT_STRINGS -->")] = QString::fromLatin1("<string name=\"app_name\">%1</string>\n") - .arg(QFileInfo(options.applicationBinary).baseName().mid(sizeof("lib") - 1)); - - if (!updateFile(fileName, replacements)) - return false; - return true; } @@ -2205,64 +2181,6 @@ QString findInPath(const QString &fileName) return QString(); } -bool buildAntProject(const Options &options) -{ - if (options.verbose) - fprintf(stdout, "Building Android package using ant.\n"); - - QString antTool = options.antTool; - if (antTool.isEmpty()) { -#if defined(Q_OS_WIN32) - antTool = findInPath(QLatin1String("ant.bat")); -#else - antTool = findInPath(QLatin1String("ant")); -#endif - } - - if (antTool.isEmpty()) { - fprintf(stderr, "Cannot find ant in PATH. Please use --ant option to pass in the correct path.\n"); - return false; - } - - if (options.verbose) - fprintf(stdout, "Using ant: %s\n", qPrintable(antTool)); - - QString oldPath = QDir::currentPath(); - if (!QDir::setCurrent(options.outputDirectory)) { - fprintf(stderr, "Cannot current path to %s\n", qPrintable(options.outputDirectory)); - return false; - } - - QString ant = QString::fromLatin1("%1 %2").arg(shellQuote(antTool)).arg(options.releasePackage ? QLatin1String(" release") : QLatin1String(" debug")); - - FILE *antCommand = openProcess(ant); - if (antCommand == 0) { - fprintf(stderr, "Cannot run ant command: %s\n.", qPrintable(ant)); - return false; - } - - char buffer[512]; - while (fgets(buffer, sizeof(buffer), antCommand) != 0) { - fprintf(stdout, "%s", buffer); - fflush(stdout); - } - - int errorCode = pclose(antCommand); - if (errorCode != 0) { - fprintf(stderr, "Building the android package failed!\n"); - if (!options.verbose) - fprintf(stderr, " -- For more information, run this command with --verbose.\n"); - return false; - } - - if (!QDir::setCurrent(oldPath)) { - fprintf(stderr, "Cannot change back to old path: %s\n", qPrintable(oldPath)); - return false; - } - - return true; -} - typedef QMap<QByteArray, QByteArray> GradleProperties; static GradleProperties readGradleProperties(const QString &path) @@ -2320,7 +2238,7 @@ static bool mergeGradleProperties(const QString &path, GradleProperties properti return true; } -bool buildGradleProject(const Options &options) +bool buildAndroidProject(const Options &options) { GradleProperties localProperties; localProperties["sdk.dir"] = options.sdkPath.toLocal8Bit(); @@ -2388,12 +2306,6 @@ bool buildGradleProject(const Options &options) return true; } -bool buildAndroidProject(const Options &options) -{ - return options.gradle ? buildGradleProject(options) - : buildAntProject(options); -} - bool uninstallApk(const Options &options) { if (options.verbose) @@ -2430,15 +2342,11 @@ enum PackageType { QString apkPath(const Options &options, PackageType pt) { QString path(options.outputDirectory); - if (options.gradle) { - path += QLatin1String("/build/outputs/apk/"); - QString buildType(options.releasePackage ? QLatin1String("release/") : QLatin1String("debug/")); - if (QDir(path + buildType).exists()) - path += buildType; - path += QDir(options.outputDirectory).dirName() + QLatin1Char('-'); - } else { - path += QLatin1String("/bin/QtApp-"); - } + path += QLatin1String("/build/outputs/apk/"); + QString buildType(options.releasePackage ? QLatin1String("release/") : QLatin1String("debug/")); + if (QDir(path + buildType).exists()) + path += buildType; + path += QDir(options.outputDirectory).dirName() + QLatin1Char('-'); if (options.releasePackage) { path += QLatin1String("release-"); if (pt == UnsignedAPK) @@ -2488,6 +2396,14 @@ bool installApk(const Options &options) return true; } +bool copyPackage(const Options &options) +{ + fflush(stdout); + auto from = apkPath(options, options.keyStore.isEmpty() ? UnsignedAPK : SignedAPK); + QFile::remove(options.apkPath); + return QFile::copy(from, options.apkPath); +} + bool copyStdCpp(Options *options) { if (options->verbose) @@ -2858,7 +2774,8 @@ enum ErrorCode CannotSignPackage = 15, CannotInstallApk = 16, CannotGenerateAssetsFileList = 18, - CannotCopyAndroidExtraResources = 19 + CannotCopyAndroidExtraResources = 19, + CannotCopyApk = 20 }; int main(int argc, char *argv[]) @@ -2915,8 +2832,7 @@ int main(int argc, char *argv[]) } if (options.build) { - if (options.gradle) - cleanAndroidFiles(options); + cleanAndroidFiles(options); if (Q_UNLIKELY(options.timing)) fprintf(stdout, "[TIMING] %d ms: Cleaned Android file\n", options.timer.elapsed()); @@ -2990,9 +2906,6 @@ int main(int argc, char *argv[]) if (Q_UNLIKELY(options.timing)) fprintf(stdout, "[TIMING] %d ms: Updated files\n", options.timer.elapsed()); - if (!options.gradle && !createAndroidProject(options)) - return CannotCreateAndroidProject; - if (Q_UNLIKELY(options.timing)) fprintf(stdout, "[TIMING] %d ms: Created project\n", options.timer.elapsed()); @@ -3005,6 +2918,9 @@ int main(int argc, char *argv[]) if (!options.keyStore.isEmpty() && !signPackage(options)) return CannotSignPackage; + if (!options.apkPath.isEmpty() && !copyPackage(options)) + return CannotCopyApk; + if (Q_UNLIKELY(options.timing)) fprintf(stdout, "[TIMING] %d ms: Signed package\n", options.timer.elapsed()); } diff --git a/src/tools/androidtestrunner/androidtestrunner.pro b/src/tools/androidtestrunner/androidtestrunner.pro new file mode 100644 index 0000000000..641d3e0003 --- /dev/null +++ b/src/tools/androidtestrunner/androidtestrunner.pro @@ -0,0 +1,13 @@ +option(host_build) +CONFIG += console + +SOURCES += \ + main.cpp + +# Required for declarations of popen/pclose on Windows +windows: QMAKE_CXXFLAGS += -U__STRICT_ANSI__ + +DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII +DEFINES += QT_NO_FOREACH + +load(qt_app) diff --git a/src/tools/androidtestrunner/main.cpp b/src/tools/androidtestrunner/main.cpp new file mode 100644 index 0000000000..e6d6f72354 --- /dev/null +++ b/src/tools/androidtestrunner/main.cpp @@ -0,0 +1,490 @@ +/**************************************************************************** +** +** Copyright (C) 2019 BogDan Vatra <bogdan@kde.org> +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QCoreApplication> +#include <QDir> +#include <QHash> +#include <QRegExp> +#include <QSystemSemaphore> +#include <QXmlStreamReader> + +#include <algorithm> +#include <chrono> +#include <functional> +#include <thread> + +#ifdef Q_CC_MSVC +#define popen _popen +#define QT_POPEN_READ "rb" +#define pclose _pclose +#else +#define QT_POPEN_READ "r" +#endif + +struct Options +{ + bool helpRequested = false; + bool verbose = false; + std::chrono::seconds timeout{300}; // 5minutes + QString androidDeployQtCommand; + QString buildPath; + QString adbCommand{QStringLiteral("adb")}; + QString makeCommand; + QString package; + QString activity; + QStringList testArgsList; + QHash<QString, QString> outFiles; + QString testArgs; + QString apkPath; + QHash<QString, std::function<bool(const QByteArray &)>> checkFiles = { + {QStringLiteral("txt"), [](const QByteArray &data) -> bool { + return data.indexOf("\nFAIL! : ") < 0; + }}, + {QStringLiteral("csv"), [](const QByteArray &/*data*/) -> bool { + // It seems csv is broken + return true; + }}, + {QStringLiteral("xml"), [](const QByteArray &data) -> bool { + QXmlStreamReader reader{data}; + while (!reader.atEnd()) { + reader.readNext(); + if (reader.isStartElement() && reader.name() == QStringLiteral("Incident") && + reader.attributes().value(QStringLiteral("type")).toString() == QStringLiteral("fail")) { + return false; + } + } + return true; + }}, + {QStringLiteral("lightxml"), [](const QByteArray &data) -> bool { + return data.indexOf("\n<Incident type=\"fail\" ") < 0; + }}, + {QStringLiteral("xunitxml"), [](const QByteArray &data) -> bool { + QXmlStreamReader reader{data}; + while (!reader.atEnd()) { + reader.readNext(); + if (reader.isStartElement() && reader.name() == QStringLiteral("testcase") && + reader.attributes().value(QStringLiteral("result")).toString() == QStringLiteral("fail")) { + return false; + } + } + return true; + }}, + {QStringLiteral("teamcity"), [](const QByteArray &data) -> bool { + return data.indexOf("' message='Failure! |[Loc: ") < 0; + }}, + {QStringLiteral("tap"), [](const QByteArray &data) -> bool { + return data.indexOf("\nnot ok ") < 0; + }}, + }; +}; + +static Options g_options; + +static bool execCommand(const QString &command, QByteArray *output = nullptr, bool verbose = false) +{ + if (verbose) + fprintf(stdout, "Execute %s\n", command.toUtf8().constData()); + FILE *process = popen(command.toUtf8().constData(), QT_POPEN_READ); + + if (!process) { + fprintf(stderr, "Cannot execute command %s", qPrintable(command)); + return false; + } + char buffer[512]; + while (fgets(buffer, sizeof(buffer), process)) { + if (output) + output->append(buffer); + if (verbose) + fprintf(stdout, "%s", buffer); + } + return pclose(process) == 0; +} + +// Copy-pasted from qmake/library/ioutil.cpp +inline static bool hasSpecialChars(const QString &arg, const uchar (&iqm)[16]) +{ + for (int x = arg.length() - 1; x >= 0; --x) { + ushort c = arg.unicode()[x].unicode(); + if ((c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)))) + return true; + } + return false; +} + +static QString shellQuoteUnix(const QString &arg) +{ + // Chars that should be quoted (TM). This includes: + static const uchar iqm[] = { + 0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8, + 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78 + }; // 0-32 \'"$`<>|;&(){}*?#!~[] + + if (!arg.length()) + return QStringLiteral("\"\""); + + QString ret(arg); + if (hasSpecialChars(ret, iqm)) { + ret.replace(QLatin1Char('\''), QStringLiteral("'\\''")); + ret.prepend(QLatin1Char('\'')); + ret.append(QLatin1Char('\'')); + } + return ret; +} + +static QString shellQuoteWin(const QString &arg) +{ + // Chars that should be quoted (TM). This includes: + // - control chars & space + // - the shell meta chars "&()<>^| + // - the potential separators ,;= + static const uchar iqm[] = { + 0xff, 0xff, 0xff, 0xff, 0x45, 0x13, 0x00, 0x78, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10 + }; + + if (!arg.length()) + return QStringLiteral("\"\""); + + QString ret(arg); + if (hasSpecialChars(ret, iqm)) { + // Quotes are escaped and their preceding backslashes are doubled. + // It's impossible to escape anything inside a quoted string on cmd + // level, so the outer quoting must be "suspended". + ret.replace(QRegExp(QStringLiteral("(\\\\*)\"")), QStringLiteral("\"\\1\\1\\^\"\"")); + // The argument must not end with a \ since this would be interpreted + // as escaping the quote -- rather put the \ behind the quote: e.g. + // rather use "foo"\ than "foo\" + int i = ret.length(); + while (i > 0 && ret.at(i - 1) == QLatin1Char('\\')) + --i; + ret.insert(i, QLatin1Char('"')); + ret.prepend(QLatin1Char('"')); + } + return ret; +} + +static QString shellQuote(const QString &arg) +{ + if (QDir::separator() == QLatin1Char('\\')) + return shellQuoteWin(arg); + else + return shellQuoteUnix(arg); +} + +static bool parseOptions() +{ + QStringList arguments = QCoreApplication::arguments(); + int i = 1; + for (; i < arguments.size(); ++i) { + const QString &argument = arguments.at(i); + if (argument.compare(QStringLiteral("--androiddeployqt"), Qt::CaseInsensitive) == 0) { + if (i + 1 == arguments.size()) + g_options.helpRequested = true; + else + g_options.androidDeployQtCommand = arguments.at(++i).trimmed(); + } else if (argument.compare(QStringLiteral("--adb"), Qt::CaseInsensitive) == 0) { + if (i + 1 == arguments.size()) + g_options.helpRequested = true; + else + g_options.adbCommand = arguments.at(++i); + } else if (argument.compare(QStringLiteral("--path"), Qt::CaseInsensitive) == 0) { + if (i + 1 == arguments.size()) + g_options.helpRequested = true; + else + g_options.buildPath = arguments.at(++i); + } else if (argument.compare(QStringLiteral("--make"), Qt::CaseInsensitive) == 0) { + if (i + 1 == arguments.size()) + g_options.helpRequested = true; + else + g_options.makeCommand = arguments.at(++i); + } else if (argument.compare(QStringLiteral("--apk"), Qt::CaseInsensitive) == 0) { + if (i + 1 == arguments.size()) + g_options.helpRequested = true; + else + g_options.apkPath = arguments.at(++i); + } else if (argument.compare(QStringLiteral("--activity"), Qt::CaseInsensitive) == 0) { + if (i + 1 == arguments.size()) + g_options.helpRequested = true; + else + g_options.activity = arguments.at(++i); + } else if (argument.compare(QStringLiteral("--timeout"), Qt::CaseInsensitive) == 0) { + if (i + 1 == arguments.size()) + g_options.helpRequested = true; + else + g_options.timeout = std::chrono::seconds{arguments.at(++i).toInt()}; + } else if (argument.compare(QStringLiteral("--help"), Qt::CaseInsensitive) == 0) { + g_options.helpRequested = true; + } else if (argument.compare(QStringLiteral("--verbose"), Qt::CaseInsensitive) == 0) { + g_options.verbose = true; + } else if (argument.compare(QStringLiteral("--"), Qt::CaseInsensitive) == 0) { + ++i; + break; + } else { + g_options.testArgsList << arguments.at(i); + } + } + for (;i < arguments.size(); ++i) + g_options.testArgsList << arguments.at(i); + + if (g_options.helpRequested || g_options.androidDeployQtCommand.isEmpty() || g_options.buildPath.isEmpty()) + return false; + + QString serial = qEnvironmentVariable("ANDROID_DEVICE_SERIAL"); + if (!serial.isEmpty()) + g_options.adbCommand += QStringLiteral(" -s %1").arg(serial); + return true; +} + +static void printHelp() +{// "012345678901234567890123456789012345678901234567890123456789012345678901" + fprintf(stderr, "Syntax: %s <options> -- [TESTARGS] \n" + "\n" + " Creates an Android package in a temp directory <destination> and\n" + " runs it on the default emulator/device or on the one specified by\n" + " \"ANDROID_DEVICE_SERIAL\" environment variable.\n\n" + " Mandatory arguments:\n" + " --androiddeployqt <androiddeployqt cmd>: The androiddeployqt:\n" + " path including its additional arguments.\n" + " --path <path>: The path where androiddeployqt will build the .apk.\n" + " Optional arguments:\n" + " --adb <adb cmd>: The Android ADB command. If missing the one from\n" + " $PATH will be used.\n" + " --activity <acitvity>: The Activity to run. If missing the first\n" + " activity from AndroidManifest.qml file will be used.\n" + " --timout <seconds>: Timeout to run the test.\n" + " Default is 5 minutes.\n" + " --make <make cmd>: make command, needed to install the qt library.\n" + " If make is missing make sure the --path is set.\n" + " --apk <apk path>: If the apk is specified and if exists, we'll skip\n" + " the package building.\n" + " -- arguments that will be passed to the test application.\n" + " --verbose: Prints out information during processing.\n" + " --help: Displays this information.\n\n", + qPrintable(QCoreApplication::arguments().at(0)) + ); +} + +static QString packageNameFromAndroidManifest(const QString &androidManifestPath) +{ + QFile androidManifestXml(androidManifestPath); + if (androidManifestXml.open(QIODevice::ReadOnly)) { + QXmlStreamReader reader(&androidManifestXml); + while (!reader.atEnd()) { + reader.readNext(); + if (reader.isStartElement() && reader.name() == QStringLiteral("manifest")) + return reader.attributes().value(QStringLiteral("package")).toString(); + } + } + return {}; +} + +static QString activityFromAndroidManifest(const QString &androidManifestPath) +{ + QFile androidManifestXml(androidManifestPath); + if (androidManifestXml.open(QIODevice::ReadOnly)) { + QXmlStreamReader reader(&androidManifestXml); + while (!reader.atEnd()) { + reader.readNext(); + if (reader.isStartElement() && reader.name() == QStringLiteral("activity")) + return reader.attributes().value(QStringLiteral("android:name")).toString(); + } + } + return {}; +} + +static void setOutputFile(QString file, QString format) +{ + if (file.isEmpty()) + file = QStringLiteral("-"); + if (format.isEmpty()) + format = QStringLiteral("txt"); + + g_options.outFiles[format] = file; +} + +static bool parseTestArgs() +{ + QRegExp newLoggingFormat{QStringLiteral("(.*),(txt|csv|xunitxml|xml|lightxml|teamcity|tap)")}; + QRegExp oldFormats{QStringLiteral("-(txt|csv|xunitxml|xml|lightxml|teamcity|tap)")}; + + QString file; + QString logType; + QString unhandledArgs; + for (int i = 0; i < g_options.testArgsList.size(); ++i) { + const QString &arg = g_options.testArgsList[i].trimmed(); + if (arg == QStringLiteral("-o")) { + if (i >= g_options.testArgsList.size() - 1) + return false; // missing file argument + + const auto &filePath = g_options.testArgsList[++i]; + if (!newLoggingFormat.exactMatch(filePath)) { + file = filePath; + } else { + const auto capturedTexts = newLoggingFormat.capturedTexts(); + setOutputFile(capturedTexts.at(1), capturedTexts.at(2)); + } + } else if (oldFormats.exactMatch(arg)) { + logType = oldFormats.capturedTexts().at(1); + } else { + unhandledArgs += QStringLiteral(" %1").arg(arg); + } + } + if (g_options.outFiles.isEmpty() || !file.isEmpty() || !logType.isEmpty()) + setOutputFile(file, logType); + + for (const auto &format : g_options.outFiles.keys()) + g_options.testArgs += QStringLiteral(" -o output.%1,%1").arg(format); + + g_options.testArgs += unhandledArgs; + g_options.testArgs = QStringLiteral("shell am start -e applicationArguments \"'%1'\" -n %2/%3").arg(shellQuote(g_options.testArgs.trimmed()), + g_options.package, + g_options.activity); + return true; +} + +static bool isRunning() { + QByteArray output; + if (!execCommand(QStringLiteral("%1 shell \"ps | grep ' %2'\"").arg(g_options.adbCommand, + shellQuote(g_options.package)), &output)) { + + return false; + } + return output.indexOf(" " + g_options.package.toUtf8()) > -1; +} + +static bool waitToFinish() +{ + using clock = std::chrono::system_clock; + auto start = clock::now(); + // wait to start + while (!isRunning()) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + if ((clock::now() - start) > std::chrono::seconds{10}) + return false; + } + + // Wait to finish + while (isRunning()) { + std::this_thread::sleep_for(std::chrono::milliseconds(250)); + if ((clock::now() - start) > g_options.timeout) + return false; + } + return true; +} + + +static bool pullFiles() +{ + bool ret = true; + for (auto it = g_options.outFiles.constBegin(); it != g_options.outFiles.end(); ++it) { + QByteArray output; + if (!execCommand(QStringLiteral("%1 shell run-as %2 cat files/output.%3") + .arg(g_options.adbCommand, g_options.package, it.key()), &output)) { + return false; + } + auto checkerIt = g_options.checkFiles.find(it.key()); + ret &= checkerIt != g_options.checkFiles.end() && checkerIt.value()(output); + if (it.value() == QStringLiteral("-")){ + fprintf(stdout, "%s", output.constData()); + fflush(stdout); + } else { + QFile out{it.value()}; + if (!out.open(QIODevice::WriteOnly)) + return false; + out.write(output); + } + } + return ret; +} + +struct RunnerLocker +{ + RunnerLocker() + { + runner.acquire(); + } + ~RunnerLocker() + { + runner.release(); + } + QSystemSemaphore runner{QStringLiteral("androidtestrunner"), 1, QSystemSemaphore::Open}; +}; + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + if (!parseOptions()) { + printHelp(); + return 1; + } + + RunnerLocker lock; // do not install or run packages while another test is running + if (!g_options.apkPath.isEmpty() && QFile::exists(g_options.apkPath)) { + if (!execCommand(QStringLiteral("%1 install -r %2") + .arg(g_options.adbCommand, g_options.apkPath), nullptr, g_options.verbose)) { + return 1; + } + } else { + if (!g_options.makeCommand.isEmpty()) { + // we need to run make INSTALL_ROOT=path install to install the application file(s) first + if (!execCommand(QStringLiteral("%1 INSTALL_ROOT=%2 install") + .arg(g_options.makeCommand, QDir::toNativeSeparators(g_options.buildPath)), nullptr, g_options.verbose)) { + return 1; + } + } + + // Run androiddeployqt + static auto verbose = g_options.verbose ? QStringLiteral("--verbose") : QStringLiteral(); + if (!execCommand(QStringLiteral("%1 %3 --reinstall --output %2 --apk %4").arg(g_options.androidDeployQtCommand, + g_options.buildPath, + verbose, + g_options.apkPath), nullptr, true)) { + return 1; + } + } + + QString manifest = g_options.buildPath + QStringLiteral("/AndroidManifest.xml"); + g_options.package = packageNameFromAndroidManifest(manifest); + if (g_options.activity.isEmpty()) + g_options.activity = activityFromAndroidManifest(manifest); + + // parseTestArgs depends on g_options.package + if (!parseTestArgs()) + return 1; + + // start the tests + bool res = execCommand(QStringLiteral("%1 %2").arg(g_options.adbCommand, g_options.testArgs), + nullptr, g_options.verbose) && waitToFinish(); + if (res) + res &= pullFiles(); + res &= execCommand(QStringLiteral("%1 uninstall %2").arg(g_options.adbCommand, g_options.package), + nullptr, g_options.verbose); + fflush(stdout); + return res ? 0 : 1; +} diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index 83e44ff9a4..f4d930babb 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -19,8 +19,6 @@ DEFINES += \ QT_NO_FOREACH \ QT_NO_CAST_FROM_ASCII -DEFINES -= QT_EVAL - SOURCES += \ ../../corelib/codecs/qlatincodec.cpp \ ../../corelib/codecs/qtextcodec.cpp \ @@ -44,6 +42,7 @@ SOURCES += \ ../../corelib/io/qfsfileengine.cpp \ ../../corelib/io/qfsfileengine_iterator.cpp \ ../../corelib/io/qiodevice.cpp \ + ../../corelib/io/qipaddress.cpp \ ../../corelib/io/qfiledevice.cpp \ ../../corelib/io/qresource.cpp \ ../../corelib/io/qtemporarydir.cpp \ @@ -52,11 +51,17 @@ SOURCES += \ ../../corelib/io/qstandardpaths.cpp \ ../../corelib/io/qloggingcategory.cpp \ ../../corelib/io/qloggingregistry.cpp \ + ../../corelib/io/qurl.cpp \ + ../../corelib/io/qurlidna.cpp \ + ../../corelib/io/qurlquery.cpp \ + ../../corelib/io/qurlrecode.cpp \ ../../corelib/kernel/qcoreapplication.cpp \ ../../corelib/kernel/qcoreglobaldata.cpp \ ../../corelib/kernel/qmetatype.cpp \ ../../corelib/kernel/qvariant.cpp \ ../../corelib/kernel/qsystemerror.cpp \ + ../../corelib/kernel/qsharedmemory.cpp \ + ../../corelib/kernel/qsystemsemaphore.cpp \ ../../corelib/plugin/quuid.cpp \ ../../corelib/serialization/qdatastream.cpp \ ../../corelib/serialization/qjson.cpp \ @@ -69,36 +74,42 @@ SOURCES += \ ../../corelib/serialization/qtextstream.cpp \ ../../corelib/serialization/qxmlutils.cpp \ ../../corelib/serialization/qxmlstream.cpp \ - ../../corelib/tools/qbitarray.cpp \ - ../../corelib/tools/qbytearray.cpp \ + ../../corelib/text/qbytearray.cpp \ + ../../corelib/text/qbytearraymatcher.cpp \ + ../../corelib/text/qlocale.cpp \ + ../../corelib/text/qlocale_tools.cpp \ + ../../corelib/text/qregexp.cpp \ + ../../corelib/text/qstring.cpp \ + ../../corelib/text/qstringbuilder.cpp \ + ../../corelib/text/qstring_compat.cpp \ + ../../corelib/text/qstringlist.cpp \ + ../../corelib/text/qstringview.cpp \ + ../../corelib/text/qvsnprintf.cpp \ + ../../corelib/time/qdatetime.cpp \ ../../corelib/tools/qarraydata.cpp \ - ../../corelib/tools/qbytearraymatcher.cpp \ + ../../corelib/tools/qbitarray.cpp \ ../../corelib/tools/qcommandlineparser.cpp \ ../../corelib/tools/qcommandlineoption.cpp \ ../../corelib/tools/qcryptographichash.cpp \ - ../../corelib/tools/qdatetime.cpp \ ../../corelib/tools/qhash.cpp \ ../../corelib/tools/qlist.cpp \ - ../../corelib/tools/qlinkedlist.cpp \ - ../../corelib/tools/qlocale.cpp \ - ../../corelib/tools/qlocale_tools.cpp \ ../../corelib/tools/qmap.cpp \ - ../../corelib/tools/qregexp.cpp \ ../../corelib/tools/qringbuffer.cpp \ ../../corelib/tools/qpoint.cpp \ ../../corelib/tools/qrect.cpp \ ../../corelib/tools/qsize.cpp \ ../../corelib/tools/qline.cpp \ - ../../corelib/tools/qstring.cpp \ - ../../corelib/tools/qstringbuilder.cpp \ - ../../corelib/tools/qstring_compat.cpp \ - ../../corelib/tools/qstringlist.cpp \ ../../corelib/tools/qversionnumber.cpp \ - ../../corelib/tools/qvsnprintf.cpp \ ../../xml/dom/qdom.cpp \ ../../xml/sax/qxml.cpp unix:SOURCES += ../../corelib/kernel/qcore_unix.cpp \ + ../../corelib/kernel/qsharedmemory_posix.cpp \ + ../../corelib/kernel/qsharedmemory_systemv.cpp \ + ../../corelib/kernel/qsharedmemory_unix.cpp \ + ../../corelib/kernel/qsystemsemaphore_posix.cpp \ + ../../corelib/kernel/qsystemsemaphore_systemv.cpp \ + ../../corelib/kernel/qsystemsemaphore_unix.cpp \ ../../corelib/io/qfilesystemengine_unix.cpp \ ../../corelib/io/qfilesystemiterator_unix.cpp \ ../../corelib/io/qfsfileengine_unix.cpp @@ -108,12 +119,18 @@ win32:SOURCES += ../../corelib/global/qoperatingsystemversion_win.cpp \ ../../corelib/io/qfilesystemiterator_win.cpp \ ../../corelib/io/qfsfileengine_win.cpp \ ../../corelib/kernel/qcoreapplication_win.cpp \ + ../../corelib/kernel/qsharedmemory_win.cpp \ + ../../corelib/kernel/qsystemsemaphore_win.cpp \ ../../corelib/plugin/qsystemlibrary.cpp \ mac { SOURCES += \ ../../corelib/kernel/qcoreapplication_mac.cpp \ - ../../corelib/kernel/qcore_mac.cpp + ../../corelib/kernel/qcore_mac.cpp \ + ../../corelib/io/qfilesystemengine_unix.cpp \ + ../../corelib/io/qfilesystemiterator_unix.cpp \ + ../../corelib/io/qfsfileengine_unix.cpp + OBJECTIVE_SOURCES += \ ../../corelib/global/qoperatingsystemversion_darwin.mm \ ../../corelib/kernel/qcore_mac_objc.mm \ diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index 0640e1b603..41d0bbf2a1 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -1652,6 +1652,12 @@ void Generator::generatePluginMetaData() jsonObjectToCbor(&map, o); } + if (!cdef->pluginData.uri.isEmpty()) { + dev.nextItem("\"URI\""); + cbor_encode_int(&map, int(QtPluginMetaDataKeys::URI)); + cbor_encode_text_string(&map, cdef->pluginData.uri.constData(), cdef->pluginData.uri.size()); + } + // Add -M args from the command line: for (auto it = cdef->pluginData.metaArgs.cbegin(), end = cdef->pluginData.metaArgs.cend(); it != end; ++it) { const QJsonArray &a = it.value(); diff --git a/src/tools/moc/generator.h b/src/tools/moc/generator.h index 134166580b..eae0353199 100644 --- a/src/tools/moc/generator.h +++ b/src/tools/moc/generator.h @@ -39,7 +39,7 @@ class Generator ClassDef *cdef; QVector<uint> meta_data; public: - Generator(ClassDef *classDef, const QVector<QByteArray> &metaTypes, const QHash<QByteArray, QByteArray> &knownQObjectClasses, const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile = 0); + Generator(ClassDef *classDef, const QVector<QByteArray> &metaTypes, const QHash<QByteArray, QByteArray> &knownQObjectClasses, const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile = nullptr); void generateCode(); private: bool registerableMetaType(const QByteArray &propertyType); diff --git a/src/tools/moc/keywords.cpp b/src/tools/moc/keywords.cpp index 07c59d155f..7da8d94efc 100644 --- a/src/tools/moc/keywords.cpp +++ b/src/tools/moc/keywords.cpp @@ -30,12 +30,12 @@ // DO NOT EDIT. static const short keyword_trans[][128] = { - {0,0,0,0,0,0,0,0,0,561,558,0,0,0,0,0, + {0,0,0,0,0,0,0,0,0,568,565,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 561,252,559,562,8,38,239,560,25,26,236,234,30,235,27,237, + 568,252,566,569,8,38,239,567,25,26,236,234,30,235,27,237, 22,22,22,22,22,22,22,22,22,22,34,41,23,39,24,43, 0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,21,8,8,8,8,8,8,8,8,8,31,564,32,238,8, + 8,21,8,8,8,8,8,8,8,8,8,31,571,32,238,8, 0,1,2,3,4,5,6,7,8,9,8,8,10,11,12,13, 14,8,15,16,17,18,19,20,8,8,8,36,245,37,248,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -116,7 +116,7 @@ static const short keyword_trans[][128] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,290,222,0,0,490,0,0,0, + 0,0,0,0,0,0,0,0,290,222,0,0,497,0,0,0, 0,0,0,0,55,0,0,330,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -155,7 +155,7 @@ static const short keyword_trans[][128] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,514,0,0,0,0,0,0,0,0,0,0,357, + 0,0,0,0,521,0,0,0,0,0,0,0,0,0,0,357, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -177,7 +177,7 @@ static const short keyword_trans[][128] = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,42,0,0,0,28,0, - 567,567,567,567,567,567,567,567,567,567,0,0,0,0,0,0, + 574,574,574,574,574,574,574,574,574,574,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -336,7 +336,7 @@ static const short keyword_trans[][128] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,566,0,0,0,0,565, + 0,0,0,0,0,0,0,0,0,0,573,0,0,0,0,572, 0,0,0,0,0,0,0,0,0,0,0,0,0,258,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -372,29 +372,29 @@ static const short keyword_trans[][128] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,487,0,0,0,300,0,0,0,0,0,0,0,0,0,0, + 0,494,0,0,0,300,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,468,417,401,409,373,0,477,0,0,0,0,364,358, - 379,0,550,465,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,475,424,408,416,380,0,484,0,0,0,0,364,358, + 386,0,557,472,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,387,0,0,0, - 0,0,380,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,394,0,0,0, + 0,0,387,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,504,0,0,0,0,0,381, + 0,0,0,0,0,0,0,0,0,511,0,0,0,0,0,388, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, @@ -403,7 +403,7 @@ static const short keyword_trans[][128] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,405,0,0,0,0,0,0,0,0,0,0,0,406, + 0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,413, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -411,14 +411,14 @@ static const short keyword_trans[][128] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,413,0,0,0,0,0,0,0,0,0,0,0,414, + 0,0,0,420,0,0,0,0,0,0,0,0,0,0,0,421, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,447,425,0,0,430,0,0,0,439,0,0, + 0,0,0,0,0,454,432,0,0,437,0,0,0,446,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, @@ -426,7 +426,7 @@ static const short keyword_trans[][128] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,533,0,466,0,0,0,494,0,0,500,0,0,0, + 0,0,0,540,0,473,0,0,0,501,0,0,507,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, @@ -435,7 +435,7 @@ static const short keyword_trans[][128] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,479,0,526,0,0,0,0,0,0,0,0,0, + 0,0,0,0,486,0,533,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -443,7 +443,7 @@ static const short keyword_trans[][128] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 542,0,0,510,0,0,0,0,0,0,0,0,0,0,0,0, + 549,0,0,517,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} }; @@ -828,197 +828,204 @@ static const struct {CHARACTER, 0, 65, 370, CHARACTER}, {CHARACTER, 0, 67, 371, CHARACTER}, {CHARACTER, 0, 69, 372, CHARACTER}, - {Q_NAMESPACE_TOKEN, 0, 0, 0, CHARACTER}, - {CHARACTER, 0, 65, 374, CHARACTER}, - {CHARACTER, 0, 68, 375, CHARACTER}, - {CHARACTER, 0, 71, 376, CHARACTER}, - {CHARACTER, 0, 69, 377, CHARACTER}, - {CHARACTER, 0, 84, 378, CHARACTER}, + {Q_NAMESPACE_TOKEN, 0, 95, 373, CHARACTER}, + {CHARACTER, 0, 69, 374, CHARACTER}, + {CHARACTER, 0, 88, 375, CHARACTER}, + {CHARACTER, 0, 80, 376, CHARACTER}, + {CHARACTER, 0, 79, 377, CHARACTER}, + {CHARACTER, 0, 82, 378, CHARACTER}, + {CHARACTER, 0, 84, 379, CHARACTER}, + {Q_NAMESPACE_EXPORT_TOKEN, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 65, 381, CHARACTER}, + {CHARACTER, 0, 68, 382, CHARACTER}, + {CHARACTER, 0, 71, 383, CHARACTER}, + {CHARACTER, 0, 69, 384, CHARACTER}, + {CHARACTER, 0, 84, 385, CHARACTER}, {Q_GADGET_TOKEN, 0, 0, 0, CHARACTER}, {CHARACTER, 44, 0, 0, CHARACTER}, {CHARACTER, 45, 0, 0, CHARACTER}, - {CHARACTER, 0, 80, 382, CHARACTER}, - {CHARACTER, 0, 69, 383, CHARACTER}, - {CHARACTER, 0, 82, 384, CHARACTER}, - {CHARACTER, 0, 84, 385, CHARACTER}, - {CHARACTER, 0, 89, 386, CHARACTER}, + {CHARACTER, 0, 80, 389, CHARACTER}, + {CHARACTER, 0, 69, 390, CHARACTER}, + {CHARACTER, 0, 82, 391, CHARACTER}, + {CHARACTER, 0, 84, 392, CHARACTER}, + {CHARACTER, 0, 89, 393, CHARACTER}, {Q_PROPERTY_TOKEN, 0, 0, 0, CHARACTER}, - {CHARACTER, 0, 85, 388, CHARACTER}, - {CHARACTER, 0, 71, 389, CHARACTER}, - {CHARACTER, 0, 73, 390, CHARACTER}, - {CHARACTER, 0, 78, 391, CHARACTER}, - {CHARACTER, 0, 95, 392, CHARACTER}, - {CHARACTER, 0, 77, 393, CHARACTER}, - {CHARACTER, 0, 69, 394, CHARACTER}, - {CHARACTER, 0, 84, 395, CHARACTER}, - {CHARACTER, 0, 65, 396, CHARACTER}, - {CHARACTER, 0, 68, 397, CHARACTER}, - {CHARACTER, 0, 65, 398, CHARACTER}, - {CHARACTER, 0, 84, 399, CHARACTER}, - {CHARACTER, 0, 65, 400, CHARACTER}, + {CHARACTER, 0, 85, 395, CHARACTER}, + {CHARACTER, 0, 71, 396, CHARACTER}, + {CHARACTER, 0, 73, 397, CHARACTER}, + {CHARACTER, 0, 78, 398, CHARACTER}, + {CHARACTER, 0, 95, 399, CHARACTER}, + {CHARACTER, 0, 77, 400, CHARACTER}, + {CHARACTER, 0, 69, 401, CHARACTER}, + {CHARACTER, 0, 84, 402, CHARACTER}, + {CHARACTER, 0, 65, 403, CHARACTER}, + {CHARACTER, 0, 68, 404, CHARACTER}, + {CHARACTER, 0, 65, 405, CHARACTER}, + {CHARACTER, 0, 84, 406, CHARACTER}, + {CHARACTER, 0, 65, 407, CHARACTER}, {Q_PLUGIN_METADATA_TOKEN, 0, 0, 0, CHARACTER}, - {CHARACTER, 0, 78, 402, CHARACTER}, - {CHARACTER, 0, 85, 403, CHARACTER}, - {CHARACTER, 0, 77, 404, CHARACTER}, + {CHARACTER, 0, 78, 409, CHARACTER}, + {CHARACTER, 0, 85, 410, CHARACTER}, + {CHARACTER, 0, 77, 411, CHARACTER}, {Q_ENUM_TOKEN, 46, 0, 0, CHARACTER}, {Q_ENUMS_TOKEN, 0, 0, 0, CHARACTER}, - {CHARACTER, 0, 78, 407, CHARACTER}, - {CHARACTER, 0, 83, 408, CHARACTER}, + {CHARACTER, 0, 78, 414, CHARACTER}, + {CHARACTER, 0, 83, 415, CHARACTER}, {Q_ENUM_NS_TOKEN, 0, 0, 0, CHARACTER}, - {CHARACTER, 0, 76, 410, CHARACTER}, - {CHARACTER, 0, 65, 411, CHARACTER}, - {CHARACTER, 0, 71, 412, CHARACTER}, + {CHARACTER, 0, 76, 417, CHARACTER}, + {CHARACTER, 0, 65, 418, CHARACTER}, + {CHARACTER, 0, 71, 419, CHARACTER}, {Q_FLAG_TOKEN, 47, 0, 0, CHARACTER}, {Q_FLAGS_TOKEN, 0, 0, 0, CHARACTER}, - {CHARACTER, 0, 78, 415, CHARACTER}, - {CHARACTER, 0, 83, 416, CHARACTER}, + {CHARACTER, 0, 78, 422, CHARACTER}, + {CHARACTER, 0, 83, 423, CHARACTER}, {Q_FLAG_NS_TOKEN, 0, 0, 0, CHARACTER}, - {CHARACTER, 0, 69, 418, CHARACTER}, - {CHARACTER, 0, 67, 419, CHARACTER}, - {CHARACTER, 0, 76, 420, CHARACTER}, - {CHARACTER, 0, 65, 421, CHARACTER}, - {CHARACTER, 0, 82, 422, CHARACTER}, - {CHARACTER, 0, 69, 423, CHARACTER}, - {CHARACTER, 0, 95, 424, CHARACTER}, + {CHARACTER, 0, 69, 425, CHARACTER}, + {CHARACTER, 0, 67, 426, CHARACTER}, + {CHARACTER, 0, 76, 427, CHARACTER}, + {CHARACTER, 0, 65, 428, CHARACTER}, + {CHARACTER, 0, 82, 429, CHARACTER}, + {CHARACTER, 0, 69, 430, CHARACTER}, + {CHARACTER, 0, 95, 431, CHARACTER}, {CHARACTER, 48, 0, 0, CHARACTER}, - {CHARACTER, 0, 76, 426, CHARACTER}, - {CHARACTER, 0, 65, 427, CHARACTER}, - {CHARACTER, 0, 71, 428, CHARACTER}, - {CHARACTER, 0, 83, 429, CHARACTER}, + {CHARACTER, 0, 76, 433, CHARACTER}, + {CHARACTER, 0, 65, 434, CHARACTER}, + {CHARACTER, 0, 71, 435, CHARACTER}, + {CHARACTER, 0, 83, 436, CHARACTER}, {Q_DECLARE_FLAGS_TOKEN, 0, 0, 0, CHARACTER}, - {CHARACTER, 0, 78, 431, CHARACTER}, - {CHARACTER, 0, 84, 432, CHARACTER}, - {CHARACTER, 0, 69, 433, CHARACTER}, - {CHARACTER, 0, 82, 434, CHARACTER}, - {CHARACTER, 0, 70, 435, CHARACTER}, - {CHARACTER, 0, 65, 436, CHARACTER}, - {CHARACTER, 0, 67, 437, CHARACTER}, - {CHARACTER, 0, 69, 438, CHARACTER}, - {Q_DECLARE_INTERFACE_TOKEN, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 78, 438, CHARACTER}, + {CHARACTER, 0, 84, 439, CHARACTER}, {CHARACTER, 0, 69, 440, CHARACTER}, - {CHARACTER, 0, 84, 441, CHARACTER}, - {CHARACTER, 0, 65, 442, CHARACTER}, - {CHARACTER, 0, 84, 443, CHARACTER}, - {CHARACTER, 0, 89, 444, CHARACTER}, - {CHARACTER, 0, 80, 445, CHARACTER}, - {CHARACTER, 0, 69, 446, CHARACTER}, + {CHARACTER, 0, 82, 441, CHARACTER}, + {CHARACTER, 0, 70, 442, CHARACTER}, + {CHARACTER, 0, 65, 443, CHARACTER}, + {CHARACTER, 0, 67, 444, CHARACTER}, + {CHARACTER, 0, 69, 445, CHARACTER}, + {Q_DECLARE_INTERFACE_TOKEN, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 69, 447, CHARACTER}, + {CHARACTER, 0, 84, 448, CHARACTER}, + {CHARACTER, 0, 65, 449, CHARACTER}, + {CHARACTER, 0, 84, 450, CHARACTER}, + {CHARACTER, 0, 89, 451, CHARACTER}, + {CHARACTER, 0, 80, 452, CHARACTER}, + {CHARACTER, 0, 69, 453, CHARACTER}, {Q_DECLARE_METATYPE_TOKEN, 0, 0, 0, CHARACTER}, - {CHARACTER, 0, 88, 448, CHARACTER}, - {CHARACTER, 0, 84, 449, CHARACTER}, - {CHARACTER, 0, 69, 450, CHARACTER}, - {CHARACTER, 0, 78, 451, CHARACTER}, - {CHARACTER, 0, 83, 452, CHARACTER}, - {CHARACTER, 0, 73, 453, CHARACTER}, - {CHARACTER, 0, 79, 454, CHARACTER}, - {CHARACTER, 0, 78, 455, CHARACTER}, - {CHARACTER, 0, 95, 456, CHARACTER}, - {CHARACTER, 0, 73, 457, CHARACTER}, + {CHARACTER, 0, 88, 455, CHARACTER}, + {CHARACTER, 0, 84, 456, CHARACTER}, + {CHARACTER, 0, 69, 457, CHARACTER}, {CHARACTER, 0, 78, 458, CHARACTER}, - {CHARACTER, 0, 84, 459, CHARACTER}, - {CHARACTER, 0, 69, 460, CHARACTER}, - {CHARACTER, 0, 82, 461, CHARACTER}, - {CHARACTER, 0, 70, 462, CHARACTER}, - {CHARACTER, 0, 65, 463, CHARACTER}, - {CHARACTER, 0, 67, 464, CHARACTER}, - {CHARACTER, 0, 69, 438, CHARACTER}, - {CHARACTER, 49, 0, 0, CHARACTER}, - {CHARACTER, 0, 84, 467, CHARACTER}, - {CHARACTER, 0, 83, 413, CHARACTER}, - {CHARACTER, 0, 76, 469, CHARACTER}, + {CHARACTER, 0, 83, 459, CHARACTER}, + {CHARACTER, 0, 73, 460, CHARACTER}, + {CHARACTER, 0, 79, 461, CHARACTER}, + {CHARACTER, 0, 78, 462, CHARACTER}, + {CHARACTER, 0, 95, 463, CHARACTER}, + {CHARACTER, 0, 73, 464, CHARACTER}, + {CHARACTER, 0, 78, 465, CHARACTER}, + {CHARACTER, 0, 84, 466, CHARACTER}, + {CHARACTER, 0, 69, 467, CHARACTER}, + {CHARACTER, 0, 82, 468, CHARACTER}, + {CHARACTER, 0, 70, 469, CHARACTER}, {CHARACTER, 0, 65, 470, CHARACTER}, - {CHARACTER, 0, 83, 471, CHARACTER}, - {CHARACTER, 0, 83, 472, CHARACTER}, - {CHARACTER, 0, 73, 473, CHARACTER}, - {CHARACTER, 0, 78, 474, CHARACTER}, - {CHARACTER, 0, 70, 475, CHARACTER}, - {CHARACTER, 0, 79, 476, CHARACTER}, + {CHARACTER, 0, 67, 471, CHARACTER}, + {CHARACTER, 0, 69, 445, CHARACTER}, + {CHARACTER, 49, 0, 0, CHARACTER}, + {CHARACTER, 0, 84, 474, CHARACTER}, + {CHARACTER, 0, 83, 420, CHARACTER}, + {CHARACTER, 0, 76, 476, CHARACTER}, + {CHARACTER, 0, 65, 477, CHARACTER}, + {CHARACTER, 0, 83, 478, CHARACTER}, + {CHARACTER, 0, 83, 479, CHARACTER}, + {CHARACTER, 0, 73, 480, CHARACTER}, + {CHARACTER, 0, 78, 481, CHARACTER}, + {CHARACTER, 0, 70, 482, CHARACTER}, + {CHARACTER, 0, 79, 483, CHARACTER}, {Q_CLASSINFO_TOKEN, 0, 0, 0, CHARACTER}, - {CHARACTER, 0, 78, 478, CHARACTER}, + {CHARACTER, 0, 78, 485, CHARACTER}, {CHARACTER, 50, 0, 0, CHARACTER}, - {CHARACTER, 0, 69, 480, CHARACTER}, - {CHARACTER, 0, 82, 481, CHARACTER}, - {CHARACTER, 0, 70, 482, CHARACTER}, - {CHARACTER, 0, 65, 483, CHARACTER}, - {CHARACTER, 0, 67, 484, CHARACTER}, - {CHARACTER, 0, 69, 485, CHARACTER}, - {CHARACTER, 0, 83, 486, CHARACTER}, + {CHARACTER, 0, 69, 487, CHARACTER}, + {CHARACTER, 0, 82, 488, CHARACTER}, + {CHARACTER, 0, 70, 489, CHARACTER}, + {CHARACTER, 0, 65, 490, CHARACTER}, + {CHARACTER, 0, 67, 491, CHARACTER}, + {CHARACTER, 0, 69, 492, CHARACTER}, + {CHARACTER, 0, 83, 493, CHARACTER}, {Q_INTERFACES_TOKEN, 0, 0, 0, CHARACTER}, - {CHARACTER, 0, 108, 488, CHARACTER}, - {CHARACTER, 0, 115, 489, CHARACTER}, + {CHARACTER, 0, 108, 495, CHARACTER}, + {CHARACTER, 0, 115, 496, CHARACTER}, {SIGNALS, 0, 0, 0, CHARACTER}, - {CHARACTER, 0, 111, 491, CHARACTER}, - {CHARACTER, 0, 116, 492, CHARACTER}, - {CHARACTER, 0, 115, 493, CHARACTER}, + {CHARACTER, 0, 111, 498, CHARACTER}, + {CHARACTER, 0, 116, 499, CHARACTER}, + {CHARACTER, 0, 115, 500, CHARACTER}, {SLOTS, 0, 0, 0, CHARACTER}, - {CHARACTER, 0, 71, 495, CHARACTER}, - {CHARACTER, 0, 78, 496, CHARACTER}, - {CHARACTER, 0, 65, 497, CHARACTER}, - {CHARACTER, 0, 76, 498, CHARACTER}, - {Q_SIGNAL_TOKEN, 0, 83, 499, CHARACTER}, + {CHARACTER, 0, 71, 502, CHARACTER}, + {CHARACTER, 0, 78, 503, CHARACTER}, + {CHARACTER, 0, 65, 504, CHARACTER}, + {CHARACTER, 0, 76, 505, CHARACTER}, + {Q_SIGNAL_TOKEN, 0, 83, 506, CHARACTER}, {Q_SIGNALS_TOKEN, 0, 0, 0, CHARACTER}, - {CHARACTER, 0, 79, 501, CHARACTER}, - {CHARACTER, 0, 84, 502, CHARACTER}, - {Q_SLOT_TOKEN, 0, 83, 503, CHARACTER}, + {CHARACTER, 0, 79, 508, CHARACTER}, + {CHARACTER, 0, 84, 509, CHARACTER}, + {Q_SLOT_TOKEN, 0, 83, 510, CHARACTER}, {Q_SLOTS_TOKEN, 0, 0, 0, CHARACTER}, - {CHARACTER, 0, 86, 505, CHARACTER}, - {CHARACTER, 0, 65, 506, CHARACTER}, - {CHARACTER, 0, 84, 507, CHARACTER}, - {CHARACTER, 0, 69, 508, CHARACTER}, - {CHARACTER, 0, 95, 509, CHARACTER}, + {CHARACTER, 0, 86, 512, CHARACTER}, + {CHARACTER, 0, 65, 513, CHARACTER}, + {CHARACTER, 0, 84, 514, CHARACTER}, + {CHARACTER, 0, 69, 515, CHARACTER}, + {CHARACTER, 0, 95, 516, CHARACTER}, {CHARACTER, 51, 0, 0, CHARACTER}, - {CHARACTER, 0, 76, 511, CHARACTER}, - {CHARACTER, 0, 79, 512, CHARACTER}, - {CHARACTER, 0, 84, 513, CHARACTER}, + {CHARACTER, 0, 76, 518, CHARACTER}, + {CHARACTER, 0, 79, 519, CHARACTER}, + {CHARACTER, 0, 84, 520, CHARACTER}, {Q_PRIVATE_SLOT_TOKEN, 0, 0, 0, CHARACTER}, - {CHARACTER, 0, 95, 515, CHARACTER}, - {CHARACTER, 0, 77, 516, CHARACTER}, - {CHARACTER, 0, 79, 517, CHARACTER}, - {CHARACTER, 0, 67, 518, CHARACTER}, - {CHARACTER, 0, 95, 519, CHARACTER}, - {CHARACTER, 0, 67, 520, CHARACTER}, - {CHARACTER, 0, 79, 521, CHARACTER}, - {CHARACTER, 0, 77, 522, CHARACTER}, - {CHARACTER, 0, 80, 523, CHARACTER}, - {CHARACTER, 0, 65, 524, CHARACTER}, - {CHARACTER, 0, 84, 525, CHARACTER}, + {CHARACTER, 0, 95, 522, CHARACTER}, + {CHARACTER, 0, 77, 523, CHARACTER}, + {CHARACTER, 0, 79, 524, CHARACTER}, + {CHARACTER, 0, 67, 525, CHARACTER}, + {CHARACTER, 0, 95, 526, CHARACTER}, + {CHARACTER, 0, 67, 527, CHARACTER}, + {CHARACTER, 0, 79, 528, CHARACTER}, + {CHARACTER, 0, 77, 529, CHARACTER}, + {CHARACTER, 0, 80, 530, CHARACTER}, + {CHARACTER, 0, 65, 531, CHARACTER}, + {CHARACTER, 0, 84, 532, CHARACTER}, {Q_MOC_COMPAT_TOKEN, 0, 0, 0, CHARACTER}, - {CHARACTER, 0, 79, 527, CHARACTER}, - {CHARACTER, 0, 75, 528, CHARACTER}, - {CHARACTER, 0, 65, 529, CHARACTER}, - {CHARACTER, 0, 66, 530, CHARACTER}, - {CHARACTER, 0, 76, 531, CHARACTER}, - {CHARACTER, 0, 69, 532, CHARACTER}, + {CHARACTER, 0, 79, 534, CHARACTER}, + {CHARACTER, 0, 75, 535, CHARACTER}, + {CHARACTER, 0, 65, 536, CHARACTER}, + {CHARACTER, 0, 66, 537, CHARACTER}, + {CHARACTER, 0, 76, 538, CHARACTER}, + {CHARACTER, 0, 69, 539, CHARACTER}, {Q_INVOKABLE_TOKEN, 0, 0, 0, CHARACTER}, - {CHARACTER, 0, 82, 534, CHARACTER}, - {CHARACTER, 0, 73, 535, CHARACTER}, - {CHARACTER, 0, 80, 536, CHARACTER}, - {CHARACTER, 0, 84, 537, CHARACTER}, - {CHARACTER, 0, 65, 538, CHARACTER}, - {CHARACTER, 0, 66, 539, CHARACTER}, - {CHARACTER, 0, 76, 540, CHARACTER}, - {CHARACTER, 0, 69, 541, CHARACTER}, + {CHARACTER, 0, 82, 541, CHARACTER}, + {CHARACTER, 0, 73, 542, CHARACTER}, + {CHARACTER, 0, 80, 543, CHARACTER}, + {CHARACTER, 0, 84, 544, CHARACTER}, + {CHARACTER, 0, 65, 545, CHARACTER}, + {CHARACTER, 0, 66, 546, CHARACTER}, + {CHARACTER, 0, 76, 547, CHARACTER}, + {CHARACTER, 0, 69, 548, CHARACTER}, {Q_SCRIPTABLE_TOKEN, 0, 0, 0, CHARACTER}, - {CHARACTER, 0, 82, 543, CHARACTER}, - {CHARACTER, 0, 79, 544, CHARACTER}, - {CHARACTER, 0, 80, 545, CHARACTER}, - {CHARACTER, 0, 69, 546, CHARACTER}, - {CHARACTER, 0, 82, 547, CHARACTER}, - {CHARACTER, 0, 84, 548, CHARACTER}, - {CHARACTER, 0, 89, 549, CHARACTER}, + {CHARACTER, 0, 82, 550, CHARACTER}, + {CHARACTER, 0, 79, 551, CHARACTER}, + {CHARACTER, 0, 80, 552, CHARACTER}, + {CHARACTER, 0, 69, 553, CHARACTER}, + {CHARACTER, 0, 82, 554, CHARACTER}, + {CHARACTER, 0, 84, 555, CHARACTER}, + {CHARACTER, 0, 89, 556, CHARACTER}, {Q_PRIVATE_PROPERTY_TOKEN, 0, 0, 0, CHARACTER}, - {CHARACTER, 0, 69, 551, CHARACTER}, - {CHARACTER, 0, 86, 552, CHARACTER}, - {CHARACTER, 0, 73, 553, CHARACTER}, - {CHARACTER, 0, 83, 554, CHARACTER}, - {CHARACTER, 0, 73, 555, CHARACTER}, - {CHARACTER, 0, 79, 556, CHARACTER}, - {CHARACTER, 0, 78, 557, CHARACTER}, + {CHARACTER, 0, 69, 558, CHARACTER}, + {CHARACTER, 0, 86, 559, CHARACTER}, + {CHARACTER, 0, 73, 560, CHARACTER}, + {CHARACTER, 0, 83, 561, CHARACTER}, + {CHARACTER, 0, 73, 562, CHARACTER}, + {CHARACTER, 0, 79, 563, CHARACTER}, + {CHARACTER, 0, 78, 564, CHARACTER}, {Q_REVISION_TOKEN, 0, 0, 0, CHARACTER}, {NEWLINE, 0, 0, 0, NOTOKEN}, {QUOTE, 0, 0, 0, NOTOKEN}, {SINGLEQUOTE, 0, 0, 0, NOTOKEN}, {WHITESPACE, 0, 0, 0, NOTOKEN}, - {HASH, 0, 35, 563, HASH}, + {HASH, 0, 35, 570, HASH}, {PP_HASHHASH, 0, 0, 0, NOTOKEN}, {BACKSLASH, 0, 0, 0, NOTOKEN}, {CPP_COMMENT, 0, 0, 0, NOTOKEN}, diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 5d777ece2e..50946443be 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -159,6 +159,7 @@ Type Moc::parseType() bool isVoid = false; type.firstToken = lookup(); for (;;) { + skipCxxAttributes(); switch (next()) { case SIGNED: case UNSIGNED: @@ -188,8 +189,11 @@ Type Moc::parseType() } break; } + + skipCxxAttributes(); test(ENUM) || test(CLASS) || test(STRUCT); for(;;) { + skipCxxAttributes(); switch (next()) { case IDENTIFIER: // void mySlot(unsigned myArg) @@ -281,6 +285,7 @@ bool Moc::parseEnum(EnumDef *def) break; next(IDENTIFIER); def->values += lexem(); + skipCxxAttributes(); } while (test(EQ) ? until(COMMA) : test(COMMA)); next(RBRACE); if (isTypdefEnum) { @@ -356,6 +361,15 @@ bool Moc::testFunctionAttribute(Token tok, FunctionDef *def) return false; } +bool Moc::skipCxxAttributes() +{ + auto rewind = index; + if (test(LBRACK) && test(LBRACK) && until(RBRACK) && test(RBRACK)) + return true; + index = rewind; + return false; +} + bool Moc::testFunctionRevision(FunctionDef *def) { if (test(Q_REVISION_TOKEN)) { @@ -381,7 +395,7 @@ bool Moc::parseFunction(FunctionDef *def, bool inMacro) //skip modifiers and attributes while (test(INLINE) || (test(STATIC) && (def->isStatic = true) == true) || (test(VIRTUAL) && (def->isVirtual = true) == true) //mark as virtual - || testFunctionAttribute(def) || testFunctionRevision(def)) {} + || skipCxxAttributes() || testFunctionAttribute(def) || testFunctionRevision(def)) {} bool templateFunction = (lookup() == TEMPLATE); def->type = parseType(); if (def->type.name.isEmpty()) { @@ -454,10 +468,11 @@ bool Moc::parseFunction(FunctionDef *def, bool inMacro) until(RBRACE); else if ((def->isAbstract = test(EQ))) until(SEMIC); + else if (skipCxxAttributes()) + until(SEMIC); else error(); } - if (scopedFunctionName) { const QByteArray msg = "Function declaration " + def->name + " contains extra qualification. Ignoring as signal or slot."; @@ -475,7 +490,7 @@ bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def) //skip modifiers and attributes while (test(EXPLICIT) || test(INLINE) || (test(STATIC) && (def->isStatic = true) == true) || (test(VIRTUAL) && (def->isVirtual = true) == true) //mark as virtual - || testFunctionAttribute(def) || testFunctionRevision(def)) {} + || skipCxxAttributes() || testFunctionAttribute(def) || testFunctionRevision(def)) {} bool tilde = test(TILDE); def->type = parseType(); if (def->type.name.isEmpty()) @@ -565,6 +580,7 @@ void Moc::parse() } else if (!test(SEMIC)) { NamespaceDef def; def.classname = nsName; + def.doGenerate = currentFilenames.size() <= 1; next(LBRACE); def.begin = index - 1; @@ -572,25 +588,22 @@ void Moc::parse() def.end = index; index = def.begin + 1; - const bool parseNamespace = currentFilenames.size() <= 1; - if (parseNamespace) { - for (int i = namespaceList.size() - 1; i >= 0; --i) { - if (inNamespace(&namespaceList.at(i))) { - def.qualified.prepend(namespaceList.at(i).classname + "::"); - } - } - for (const QByteArray &ns : nested) { - NamespaceDef parentNs; - parentNs.classname = ns; - parentNs.qualified = def.qualified; - def.qualified += ns + "::"; - parentNs.begin = def.begin; - parentNs.end = def.end; - namespaceList += parentNs; + for (int i = namespaceList.size() - 1; i >= 0; --i) { + if (inNamespace(&namespaceList.at(i))) { + def.qualified.prepend(namespaceList.at(i).classname + "::"); } } + for (const QByteArray &ns : nested) { + NamespaceDef parentNs; + parentNs.classname = ns; + parentNs.qualified = def.qualified; + def.qualified += ns + "::"; + parentNs.begin = def.begin; + parentNs.end = def.end; + namespaceList += parentNs; + } - while (parseNamespace && inNamespace(&def) && hasNext()) { + while (inNamespace(&def) && hasNext()) { switch (next()) { case NAMESPACE: if (test(IDENTIFIER)) { @@ -607,6 +620,13 @@ void Moc::parse() case Q_NAMESPACE_TOKEN: def.hasQNamespace = true; break; + case Q_NAMESPACE_EXPORT_TOKEN: + next(LPAREN); + while (test(IDENTIFIER)) + {} + next(RPAREN); + def.hasQNamespace = true; + break; case Q_ENUMS_TOKEN: case Q_ENUM_NS_TOKEN: parseEnumOrFlag(&def, false); @@ -915,7 +935,8 @@ void Moc::parse() } else { knownGadgets.insert(def.classname, def.qualified); knownGadgets.insert(def.qualified, def.qualified); - classList += def; + if (n.doGenerate) + classList += def; } } } @@ -1180,6 +1201,15 @@ void Moc::createPropertyDef(PropertyDef &propDef) propDef.type = type; + auto checkIsFunction = [&](const QByteArray &def, const char *name) { + if (def.endsWith(')')) { + QByteArray msg = "Providing a function for "; + msg += name; + msg += " in a property declaration is deprecated and will not be supported in Qt 6 anymore."; + warning(msg.constData()); + } + }; + next(); propDef.name = lexem(); while (test(IDENTIFIER)) { @@ -1229,11 +1259,13 @@ void Moc::createPropertyDef(PropertyDef &propDef) error(2); break; case 'S': - if (l == "SCRIPTABLE") + if (l == "SCRIPTABLE") { propDef.scriptable = v + v2; - else if (l == "STORED") + checkIsFunction(propDef.scriptable, "SCRIPTABLE"); + } else if (l == "STORED") { propDef.stored = v + v2; - else + checkIsFunction(propDef.stored, "STORED"); + } else error(2); break; case 'W': if (l != "WRITE") error(2); @@ -1241,15 +1273,18 @@ void Moc::createPropertyDef(PropertyDef &propDef) break; case 'D': if (l != "DESIGNABLE") error(2); propDef.designable = v + v2; + checkIsFunction(propDef.designable, "DESIGNABLE"); break; case 'E': if (l != "EDITABLE") error(2); propDef.editable = v + v2; + checkIsFunction(propDef.editable, "EDITABLE"); break; case 'N': if (l != "NOTIFY") error(2); propDef.notify = v; break; case 'U': if (l != "USER") error(2); propDef.user = v + v2; + checkIsFunction(propDef.user, "USER"); break; default: error(2); @@ -1297,6 +1332,9 @@ void Moc::parsePluginData(ClassDef *def) if (l == "IID") { next(STRING_LITERAL); def->pluginData.iid = unquotedLexem(); + } else if (l == "URI") { + next(STRING_LITERAL); + def->pluginData.uri = unquotedLexem(); } else if (l == "FILE") { next(STRING_LITERAL); QByteArray metaDataFile = unquotedLexem(); @@ -1337,6 +1375,7 @@ void Moc::parsePluginData(ClassDef *def) + " does not contain a valid JSON object. Declaration will be ignored"; warning(msg.constData()); def->pluginData.iid = QByteArray(); + def->pluginData.uri = QByteArray(); return; } } diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h index d6482f4e44..bb1c9501fe 100644 --- a/src/tools/moc/moc.h +++ b/src/tools/moc/moc.h @@ -167,6 +167,7 @@ struct ClassDef : BaseDef { struct PluginData { QByteArray iid; + QByteArray uri; QMap<QString, QJsonArray> metaArgs; QJsonDocument metaData; } pluginData; @@ -188,6 +189,7 @@ Q_DECLARE_TYPEINFO(ClassDef::Interface, Q_MOVABLE_TYPE); struct NamespaceDef : BaseDef { bool hasQNamespace = false; + bool doGenerate = false; }; Q_DECLARE_TYPEINFO(NamespaceDef, Q_MOVABLE_TYPE); @@ -256,6 +258,8 @@ public: bool testFunctionAttribute(Token tok, FunctionDef *def); bool testFunctionRevision(FunctionDef *def); + bool skipCxxAttributes(); + void checkSuperClasses(ClassDef *def); void checkProperties(ClassDef* cdef); }; diff --git a/src/tools/moc/parser.h b/src/tools/moc/parser.h index bedcbbf7e2..63f4cf0d9a 100644 --- a/src/tools/moc/parser.h +++ b/src/tools/moc/parser.h @@ -69,9 +69,9 @@ public: inline const Symbol &symbol() { return symbols.at(index-1);} Q_NORETURN void error(int rollback); - Q_NORETURN void error(const char *msg = 0); - void warning(const char * = 0); - void note(const char * = 0); + Q_NORETURN void error(const char *msg = nullptr); + void warning(const char * = nullptr); + void note(const char * = nullptr); }; diff --git a/src/tools/moc/token.h b/src/tools/moc/token.h index db9d319b78..0cc163f9e4 100644 --- a/src/tools/moc/token.h +++ b/src/tools/moc/token.h @@ -155,6 +155,7 @@ QT_BEGIN_NAMESPACE F(Q_OBJECT_TOKEN) \ F(Q_GADGET_TOKEN) \ F(Q_NAMESPACE_TOKEN) \ + F(Q_NAMESPACE_EXPORT_TOKEN) \ F(Q_PROPERTY_TOKEN) \ F(Q_PLUGIN_METADATA_TOKEN) \ F(Q_ENUMS_TOKEN) \ diff --git a/src/tools/moc/util/generate_keywords.cpp b/src/tools/moc/util/generate_keywords.cpp index df850c1bdc..9248e9e2e7 100644 --- a/src/tools/moc/util/generate_keywords.cpp +++ b/src/tools/moc/util/generate_keywords.cpp @@ -214,6 +214,7 @@ static const Keyword keywords[] = { { "return", "RETURN" }, { "Q_OBJECT", "Q_OBJECT_TOKEN" }, { "Q_NAMESPACE", "Q_NAMESPACE_TOKEN" }, + { "Q_NAMESPACE_EXPORT", "Q_NAMESPACE_EXPORT_TOKEN" }, { "Q_GADGET", "Q_GADGET_TOKEN" }, { "Q_PROPERTY", "Q_PROPERTY_TOKEN" }, { "Q_PLUGIN_METADATA", "Q_PLUGIN_METADATA_TOKEN" }, diff --git a/src/tools/moc/util/generate_keywords.pro b/src/tools/moc/util/generate_keywords.pro index 2bbc3ced61..e29738c18a 100644 --- a/src/tools/moc/util/generate_keywords.pro +++ b/src/tools/moc/util/generate_keywords.pro @@ -1,4 +1,5 @@ CONFIG -= moc CONFIG += cmdline +QT = core SOURCES += generate_keywords.cpp diff --git a/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp b/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp index 7c6f0bdeef..522c55593f 100644 --- a/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp +++ b/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp @@ -32,7 +32,6 @@ #include <qfile.h> #include <qlist.h> #include <qbuffer.h> -#include <qregexp.h> #include <qvector.h> #include <qdebug.h> diff --git a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp index ea410cd257..ce4232f3e8 100644 --- a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp +++ b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp @@ -161,22 +161,22 @@ static QString moc(const QString &name) static QTextStream &writeHeader(QTextStream &ts, bool changesWillBeLost) { - ts << "/*" << endl - << " * This file was generated by " PROGRAMNAME " version " PROGRAMVERSION << endl - << " * Command line was: " << commandLine << endl - << " *" << endl - << " * " PROGRAMNAME " is " PROGRAMCOPYRIGHT << endl - << " *" << endl - << " * This is an auto-generated file." << endl; + ts << "/*" << Qt::endl + << " * This file was generated by " PROGRAMNAME " version " PROGRAMVERSION << Qt::endl + << " * Command line was: " << commandLine << Qt::endl + << " *" << Qt::endl + << " * " PROGRAMNAME " is " PROGRAMCOPYRIGHT << Qt::endl + << " *" << Qt::endl + << " * This is an auto-generated file." << Qt::endl; if (changesWillBeLost) - ts << " * Do not edit! All changes made to it will be lost." << endl; + ts << " * Do not edit! All changes made to it will be lost." << Qt::endl; else - ts << " * This file may have been hand-edited. Look for HAND-EDIT comments" << endl - << " * before re-generating it." << endl; + ts << " * This file may have been hand-edited. Look for HAND-EDIT comments" << Qt::endl + << " * before re-generating it." << Qt::endl; - ts << " */" << endl - << endl; + ts << " */" << Qt::endl + << Qt::endl; return ts; } @@ -466,66 +466,66 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf } includeGuard = QString(QLatin1String("%1")) .arg(includeGuard); - hs << "#ifndef " << includeGuard << endl - << "#define " << includeGuard << endl - << endl; + hs << "#ifndef " << includeGuard << Qt::endl + << "#define " << includeGuard << Qt::endl + << Qt::endl; // include our stuff: - hs << "#include <QtCore/QObject>" << endl + hs << "#include <QtCore/QObject>" << Qt::endl << includeList - << "#include <QtDBus/QtDBus>" << endl; + << "#include <QtDBus/QtDBus>" << Qt::endl; for (const QString &include : qAsConst(includes)) { - hs << "#include \"" << include << "\"" << endl; + hs << "#include \"" << include << "\"" << Qt::endl; if (headerName.isEmpty()) - cs << "#include \"" << include << "\"" << endl; + cs << "#include \"" << include << "\"" << Qt::endl; } - hs << endl; + hs << Qt::endl; if (cppName != headerName) { if (!headerName.isEmpty() && headerName != QLatin1String("-")) - cs << "#include \"" << headerName << "\"" << endl << endl; + cs << "#include \"" << headerName << "\"" << Qt::endl << Qt::endl; } for (const QDBusIntrospection::Interface *interface : interfaces) { QString className = classNameForInterface(interface->name, Proxy); // comment: - hs << "/*" << endl - << " * Proxy class for interface " << interface->name << endl - << " */" << endl; - cs << "/*" << endl - << " * Implementation of interface class " << className << endl - << " */" << endl - << endl; + hs << "/*" << Qt::endl + << " * Proxy class for interface " << interface->name << Qt::endl + << " */" << Qt::endl; + cs << "/*" << Qt::endl + << " * Implementation of interface class " << className << Qt::endl + << " */" << Qt::endl + << Qt::endl; // class header: - hs << "class " << className << ": public QDBusAbstractInterface" << endl - << "{" << endl - << " Q_OBJECT" << endl; + hs << "class " << className << ": public QDBusAbstractInterface" << Qt::endl + << "{" << Qt::endl + << " Q_OBJECT" << Qt::endl; // the interface name - hs << "public:" << endl - << " static inline const char *staticInterfaceName()" << endl - << " { return \"" << interface->name << "\"; }" << endl - << endl; + hs << "public:" << Qt::endl + << " static inline const char *staticInterfaceName()" << Qt::endl + << " { return \"" << interface->name << "\"; }" << Qt::endl + << Qt::endl; // constructors/destructors: - hs << "public:" << endl - << " " << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);" << endl - << endl - << " ~" << className << "();" << endl - << endl; - cs << className << "::" << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)" << endl - << " : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)" << endl - << "{" << endl - << "}" << endl - << endl - << className << "::~" << className << "()" << endl - << "{" << endl - << "}" << endl - << endl; + hs << "public:" << Qt::endl + << " " << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);" << Qt::endl + << Qt::endl + << " ~" << className << "();" << Qt::endl + << Qt::endl; + cs << className << "::" << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)" << Qt::endl + << " : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)" << Qt::endl + << "{" << Qt::endl + << "}" << Qt::endl + << Qt::endl + << className << "::~" << className << "()" << Qt::endl + << "{" << Qt::endl + << "}" << Qt::endl + << Qt::endl; // properties: for (const QDBusIntrospection::Property &property : interface->properties) { @@ -545,27 +545,27 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf // it's writeable hs << " WRITE " << setter; - hs << ")" << endl; + hs << ")" << Qt::endl; // getter: if (property.access != QDBusIntrospection::Property::Write) { - hs << " inline " << type << " " << getter << "() const" << endl + hs << " inline " << type << " " << getter << "() const" << Qt::endl << " { return qvariant_cast< " << type << " >(property(\"" - << property.name << "\")); }" << endl; + << property.name << "\")); }" << Qt::endl; } // setter: if (property.access != QDBusIntrospection::Property::Read) { - hs << " inline void " << setter << "(" << constRefArg(type) << "value)" << endl + hs << " inline void " << setter << "(" << constRefArg(type) << "value)" << Qt::endl << " { setProperty(\"" << property.name - << "\", QVariant::fromValue(value)); }" << endl; + << "\", QVariant::fromValue(value)); }" << Qt::endl; } - hs << endl; + hs << Qt::endl; } // methods: - hs << "public Q_SLOTS: // METHODS" << endl; + hs << "public Q_SLOTS: // METHODS" << Qt::endl; for (const QDBusIntrospection::Method &method : interface->methods) { bool isDeprecated = method.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) == QLatin1String("true"); bool isNoReply = @@ -595,26 +595,26 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf QStringList argNames = makeArgNames(method.inputArgs); writeArgList(hs, argNames, method.annotations, method.inputArgs); - hs << ")" << endl - << " {" << endl - << " QList<QVariant> argumentList;" << endl; + hs << ")" << Qt::endl + << " {" << Qt::endl + << " QList<QVariant> argumentList;" << Qt::endl; if (!method.inputArgs.isEmpty()) { hs << " argumentList"; for (int argPos = 0; argPos < method.inputArgs.count(); ++argPos) hs << " << QVariant::fromValue(" << argNames.at(argPos) << ')'; - hs << ";" << endl; + hs << ";" << Qt::endl; } if (isNoReply) hs << " callWithArgumentList(QDBus::NoBlock, " - << "QStringLiteral(\"" << method.name << "\"), argumentList);" << endl; + << "QStringLiteral(\"" << method.name << "\"), argumentList);" << Qt::endl; else hs << " return asyncCallWithArgumentList(QStringLiteral(\"" - << method.name << "\"), argumentList);" << endl; + << method.name << "\"), argumentList);" << Qt::endl; // close the function: - hs << " }" << endl; + hs << " }" << Qt::endl; if (method.outputArgs.count() > 1) { // generate the old-form QDBusReply methods with multiple incoming parameters @@ -627,39 +627,39 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf QStringList argNames = makeArgNames(method.inputArgs, method.outputArgs); writeArgList(hs, argNames, method.annotations, method.inputArgs, method.outputArgs); - hs << ")" << endl - << " {" << endl - << " QList<QVariant> argumentList;" << endl; + hs << ")" << Qt::endl + << " {" << Qt::endl + << " QList<QVariant> argumentList;" << Qt::endl; int argPos = 0; if (!method.inputArgs.isEmpty()) { hs << " argumentList"; for (argPos = 0; argPos < method.inputArgs.count(); ++argPos) hs << " << QVariant::fromValue(" << argNames.at(argPos) << ')'; - hs << ";" << endl; + hs << ";" << Qt::endl; } hs << " QDBusMessage reply = callWithArgumentList(QDBus::Block, " - << "QStringLiteral(\"" << method.name << "\"), argumentList);" << endl; + << "QStringLiteral(\"" << method.name << "\"), argumentList);" << Qt::endl; argPos++; hs << " if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == " - << method.outputArgs.count() << ") {" << endl; + << method.outputArgs.count() << ") {" << Qt::endl; // yes, starting from 1 for (int i = 1; i < method.outputArgs.count(); ++i) hs << " " << argNames.at(argPos++) << " = qdbus_cast<" << templateArg(qtTypeName(method.outputArgs.at(i).type, method.annotations, i, "Out")) - << ">(reply.arguments().at(" << i << "));" << endl; - hs << " }" << endl - << " return reply;" << endl - << " }" << endl; + << ">(reply.arguments().at(" << i << "));" << Qt::endl; + hs << " }" << Qt::endl + << " return reply;" << Qt::endl + << " }" << Qt::endl; } - hs << endl; + hs << Qt::endl; } - hs << "Q_SIGNALS: // SIGNALS" << endl; + hs << "Q_SIGNALS: // SIGNALS" << Qt::endl; for (const QDBusIntrospection::Signal &signal : interface->signals_) { hs << " "; if (signal.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) == @@ -671,12 +671,12 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf QStringList argNames = makeArgNames(signal.outputArgs); writeSignalArgList(hs, argNames, signal.annotations, signal.outputArgs); - hs << ");" << endl; // finished for header + hs << ");" << Qt::endl; // finished for header } // close the class: - hs << "};" << endl - << endl; + hs << "};" << Qt::endl + << Qt::endl; } if (!skipNamespaces) { @@ -698,17 +698,17 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf // i parts matched // close last.arguments().count() - i namespaces: for (int j = i; j < last.count(); ++j) - hs << QString((last.count() - j - 1 + i) * 2, QLatin1Char(' ')) << "}" << endl; + hs << QString((last.count() - j - 1 + i) * 2, QLatin1Char(' ')) << "}" << Qt::endl; // open current.arguments().count() - i namespaces for (int j = i; j < current.count(); ++j) - hs << QString(j * 2, QLatin1Char(' ')) << "namespace " << current.at(j) << " {" << endl; + hs << QString(j * 2, QLatin1Char(' ')) << "namespace " << current.at(j) << " {" << Qt::endl; // add this class: if (!name.isEmpty()) { hs << QString(current.count() * 2, QLatin1Char(' ')) << "typedef ::" << classNameForInterface(it->constData()->name, Proxy) - << " " << name << ";" << endl; + << " " << name << ";" << Qt::endl; } if (it == interfaces.constEnd()) @@ -719,12 +719,12 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf } // close the include guard - hs << "#endif" << endl; + hs << "#endif" << Qt::endl; QString mocName = moc(filename); if (includeMocs && !mocName.isEmpty()) - cs << endl - << "#include \"" << mocName << "\"" << endl; + cs << Qt::endl + << "#include \"" << mocName << "\"" << Qt::endl; cs.flush(); hs.flush(); @@ -772,36 +772,36 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte } includeGuard = QString(QLatin1String("%1")) .arg(includeGuard); - hs << "#ifndef " << includeGuard << endl - << "#define " << includeGuard << endl - << endl; + hs << "#ifndef " << includeGuard << Qt::endl + << "#define " << includeGuard << Qt::endl + << Qt::endl; // include our stuff: - hs << "#include <QtCore/QObject>" << endl; + hs << "#include <QtCore/QObject>" << Qt::endl; if (cppName == headerName) - hs << "#include <QtCore/QMetaObject>" << endl - << "#include <QtCore/QVariant>" << endl; - hs << "#include <QtDBus/QtDBus>" << endl; + hs << "#include <QtCore/QMetaObject>" << Qt::endl + << "#include <QtCore/QVariant>" << Qt::endl; + hs << "#include <QtDBus/QtDBus>" << Qt::endl; for (const QString &include : qAsConst(includes)) { - hs << "#include \"" << include << "\"" << endl; + hs << "#include \"" << include << "\"" << Qt::endl; if (headerName.isEmpty()) - cs << "#include \"" << include << "\"" << endl; + cs << "#include \"" << include << "\"" << Qt::endl; } if (cppName != headerName) { if (!headerName.isEmpty() && headerName != QLatin1String("-")) - cs << "#include \"" << headerName << "\"" << endl; + cs << "#include \"" << headerName << "\"" << Qt::endl; - cs << "#include <QtCore/QMetaObject>" << endl + cs << "#include <QtCore/QMetaObject>" << Qt::endl << includeList - << endl; + << Qt::endl; hs << forwardDeclarations; } else { hs << includeList; } - hs << endl; + hs << Qt::endl; QString parent = parentClassName; if (parentClassName.isEmpty()) @@ -811,47 +811,47 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte QString className = classNameForInterface(interface->name, Adaptor); // comment: - hs << "/*" << endl - << " * Adaptor class for interface " << interface->name << endl - << " */" << endl; - cs << "/*" << endl - << " * Implementation of adaptor class " << className << endl - << " */" << endl - << endl; + hs << "/*" << Qt::endl + << " * Adaptor class for interface " << interface->name << Qt::endl + << " */" << Qt::endl; + cs << "/*" << Qt::endl + << " * Implementation of adaptor class " << className << Qt::endl + << " */" << Qt::endl + << Qt::endl; // class header: - hs << "class " << className << ": public QDBusAbstractAdaptor" << endl - << "{" << endl - << " Q_OBJECT" << endl - << " Q_CLASSINFO(\"D-Bus Interface\", \"" << interface->name << "\")" << endl - << " Q_CLASSINFO(\"D-Bus Introspection\", \"\"" << endl + hs << "class " << className << ": public QDBusAbstractAdaptor" << Qt::endl + << "{" << Qt::endl + << " Q_OBJECT" << Qt::endl + << " Q_CLASSINFO(\"D-Bus Interface\", \"" << interface->name << "\")" << Qt::endl + << " Q_CLASSINFO(\"D-Bus Introspection\", \"\"" << Qt::endl << stringify(interface->introspection) - << " \"\")" << endl - << "public:" << endl - << " " << className << "(" << parent << " *parent);" << endl - << " virtual ~" << className << "();" << endl - << endl; + << " \"\")" << Qt::endl + << "public:" << Qt::endl + << " " << className << "(" << parent << " *parent);" << Qt::endl + << " virtual ~" << className << "();" << Qt::endl + << Qt::endl; if (!parentClassName.isEmpty()) - hs << " inline " << parent << " *parent() const" << endl - << " { return static_cast<" << parent << " *>(QObject::parent()); }" << endl - << endl; + hs << " inline " << parent << " *parent() const" << Qt::endl + << " { return static_cast<" << parent << " *>(QObject::parent()); }" << Qt::endl + << Qt::endl; // constructor/destructor - cs << className << "::" << className << "(" << parent << " *parent)" << endl - << " : QDBusAbstractAdaptor(parent)" << endl - << "{" << endl - << " // constructor" << endl - << " setAutoRelaySignals(true);" << endl - << "}" << endl - << endl - << className << "::~" << className << "()" << endl - << "{" << endl - << " // destructor" << endl - << "}" << endl - << endl; - - hs << "public: // PROPERTIES" << endl; + cs << className << "::" << className << "(" << parent << " *parent)" << Qt::endl + << " : QDBusAbstractAdaptor(parent)" << Qt::endl + << "{" << Qt::endl + << " // constructor" << Qt::endl + << " setAutoRelaySignals(true);" << Qt::endl + << "}" << Qt::endl + << Qt::endl + << className << "::~" << className << "()" << Qt::endl + << "{" << Qt::endl + << " // destructor" << Qt::endl + << "}" << Qt::endl + << Qt::endl; + + hs << "public: // PROPERTIES" << Qt::endl; for (const QDBusIntrospection::Property &property : interface->properties) { QByteArray type = qtTypeName(property.type, property.annotations); QString constRefType = constRefArg(type); @@ -863,38 +863,38 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte hs << " READ " << getter; if (property.access != QDBusIntrospection::Property::Read) hs << " WRITE " << setter; - hs << ")" << endl; + hs << ")" << Qt::endl; // getter: if (property.access != QDBusIntrospection::Property::Write) { - hs << " " << type << " " << getter << "() const;" << endl; + hs << " " << type << " " << getter << "() const;" << Qt::endl; cs << type << " " - << className << "::" << getter << "() const" << endl - << "{" << endl - << " // get the value of property " << property.name << endl - << " return qvariant_cast< " << type <<" >(parent()->property(\"" << property.name << "\"));" << endl - << "}" << endl - << endl; + << className << "::" << getter << "() const" << Qt::endl + << "{" << Qt::endl + << " // get the value of property " << property.name << Qt::endl + << " return qvariant_cast< " << type <<" >(parent()->property(\"" << property.name << "\"));" << Qt::endl + << "}" << Qt::endl + << Qt::endl; } // setter if (property.access != QDBusIntrospection::Property::Read) { - hs << " void " << setter << "(" << constRefType << "value);" << endl; - cs << "void " << className << "::" << setter << "(" << constRefType << "value)" << endl - << "{" << endl - << " // set the value of property " << property.name << endl + hs << " void " << setter << "(" << constRefType << "value);" << Qt::endl; + cs << "void " << className << "::" << setter << "(" << constRefType << "value)" << Qt::endl + << "{" << Qt::endl + << " // set the value of property " << property.name << Qt::endl << " parent()->setProperty(\"" << property.name << "\", QVariant::fromValue(value"; if (constRefType.contains(QLatin1String("QDBusVariant"))) cs << ".variant()"; - cs << "));" << endl - << "}" << endl - << endl; + cs << "));" << Qt::endl + << "}" << Qt::endl + << Qt::endl; } - hs << endl; + hs << Qt::endl; } - hs << "public Q_SLOTS: // METHODS" << endl; + hs << "public Q_SLOTS: // METHODS" << Qt::endl; for (const QDBusIntrospection::Method &method : interface->methods) { bool isNoReply = method.annotations.value(QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true"); @@ -930,10 +930,10 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte writeArgList(hs, argNames, method.annotations, method.inputArgs, method.outputArgs); writeArgList(cs, argNames, method.annotations, method.inputArgs, method.outputArgs); - hs << ");" << endl; // finished for header - cs << ")" << endl - << "{" << endl - << " // handle method call " << interface->name << "." << methodName(method) << endl; + hs << ");" << Qt::endl; // finished for header + cs << ")" << Qt::endl + << "{" << Qt::endl + << " // handle method call " << interface->name << "." << methodName(method) << Qt::endl; // make the call bool usingInvokeMethod = false; @@ -945,7 +945,7 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte // we are using QMetaObject::invokeMethod if (!returnType.isEmpty()) cs << " " << returnType << " " << argNames.at(method.inputArgs.count()) - << ";" << endl; + << ";" << Qt::endl; static const char invoke[] = " QMetaObject::invokeMethod(parent(), \""; cs << invoke << name << "\""; @@ -966,10 +966,10 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte << argNames.at(i) << ")"; - cs << ");" << endl; + cs << ");" << Qt::endl; if (!returnType.isEmpty()) - cs << " return " << argNames.at(method.inputArgs.count()) << ";" << endl; + cs << " return " << argNames.at(method.inputArgs.count()) << ";" << Qt::endl; } else { if (parentClassName.isEmpty()) cs << " //"; @@ -997,13 +997,13 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte first = false; } - cs << ");" << endl; + cs << ");" << Qt::endl; } - cs << "}" << endl - << endl; + cs << "}" << Qt::endl + << Qt::endl; } - hs << "Q_SIGNALS: // SIGNALS" << endl; + hs << "Q_SIGNALS: // SIGNALS" << Qt::endl; for (const QDBusIntrospection::Signal &signal : interface->signals_) { hs << " "; if (signal.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) == @@ -1015,21 +1015,21 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte QStringList argNames = makeArgNames(signal.outputArgs); writeSignalArgList(hs, argNames, signal.annotations, signal.outputArgs); - hs << ");" << endl; // finished for header + hs << ");" << Qt::endl; // finished for header } // close the class: - hs << "};" << endl - << endl; + hs << "};" << Qt::endl + << Qt::endl; } // close the include guard - hs << "#endif" << endl; + hs << "#endif" << Qt::endl; QString mocName = moc(filename); if (includeMocs && !mocName.isEmpty()) - cs << endl - << "#include \"" << mocName << "\"" << endl; + cs << Qt::endl + << "#include \"" << mocName << "\"" << Qt::endl; cs.flush(); hs.flush(); diff --git a/src/tools/qfloat16-tables/gen_qfloat16_tables.cpp b/src/tools/qfloat16-tables/gen_qfloat16_tables.cpp deleted file mode 100644 index 17fc978039..0000000000 --- a/src/tools/qfloat16-tables/gen_qfloat16_tables.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 by Southwest Research Institute (R) -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <qfile.h> -#include <qdebug.h> - -quint32 convertmantissa(qint32 i) -{ - quint32 m = i << 13; // Zero pad mantissa bits - quint32 e = 0; // Zero exponent - - while (!(m & 0x00800000)) { // While not normalized - e -= 0x00800000; // Decrement exponent (1<<23) - m <<= 1; // Shift mantissa - } - m &= ~0x00800000; // Clear leading 1 bit - e += 0x38800000; // Adjust bias ((127-14)<<23) - return m | e; // Return combined number -} - -// we first build these tables up and then print them out as a separate step in order -// to more closely map the implementation given in the paper. -quint32 basetable[512]; -quint32 shifttable[512]; - -#define PRINTHEX(a) "0x" + QByteArray::number(a,16).toUpper() + "U,\n" - -qint32 main(qint32 argc, char **argv) -{ - if (argc < 2) { - qWarning() << "Must provide output filename as argument."; - return -1; - } - - QFile fid(QFile::decodeName(argv[1])); - if (!fid.open(QIODevice::WriteOnly | QIODevice::Text)) { - qWarning() << "Abort: Failed to open/create file" << fid.fileName(); - return -1; - } - quint32 i; - - fid.write("/* This file was generated by gen_qfloat16_tables.cpp */\n\n"); - fid.write("#include <QtCore/qfloat16.h>\n\n"); - - fid.write("QT_BEGIN_NAMESPACE\n\n"); - fid.write("#if !defined(__F16C__) && !defined(__ARM_FP16_FORMAT_IEEE)\n\n"); - - fid.write("const quint32 qfloat16::mantissatable[2048] = {\n"); - fid.write("0,\n"); - for (i = 1; i < 1024; i++) - fid.write(PRINTHEX(convertmantissa(i))); - for (i = 1024; i < 2048; i++) - fid.write(PRINTHEX(0x38000000U + ((i - 1024) << 13))); - fid.write("};\n\n"); - - fid.write("const quint32 qfloat16::exponenttable[64] = {\n"); - fid.write("0,\n"); - for (i = 1; i < 31; i++) - fid.write(PRINTHEX(i << 23)); - fid.write("0x47800000U,\n"); // 31 - fid.write("0x80000000U,\n"); // 32 - for (i = 33; i < 63; i++) - fid.write(PRINTHEX(0x80000000U + ((i - 32) << 23))); - fid.write("0xC7800000U,\n"); // 63 - fid.write("};\n\n"); - - fid.write("const quint32 qfloat16::offsettable[64] = {\n"); - fid.write("0,\n"); - for (i = 1; i < 32; i++) - fid.write("1024U,\n"); - fid.write("0,\n"); - for (i = 33; i < 64; i++) - fid.write("1024U,\n"); - fid.write("};\n\n"); - - qint32 e; - for (i = 0; i < 256; ++i) { - e = i - 127; - if (e < -24) { // Very small numbers map to zero - basetable[i | 0x000] = 0x0000; - basetable[i | 0x100] = 0x8000; - shifttable[i | 0x000] = 24; - shifttable[i | 0x100] = 24; - - } else if (e < -14) { // Small numbers map to denorms - basetable[i | 0x000] = (0x0400 >> (-e - 14)); - basetable[i | 0x100] = (0x0400 >> (-e - 14)) | 0x8000; - shifttable[i | 0x000] = -e - 1; - shifttable[i | 0x100] = -e - 1; - - } else if (e <= 15) { // Normal numbers just lose precision - basetable[i | 0x000] = ((e + 15) << 10); - basetable[i | 0x100] = ((e + 15) << 10) | 0x8000; - shifttable[i | 0x000] = 13; - shifttable[i | 0x100] = 13; - - } else if (e < 128) { // Large numbers map to Infinity - basetable[i | 0x000] = 0x7C00; - basetable[i | 0x100] = 0xFC00; - shifttable[i | 0x000] = 24; - shifttable[i | 0x100] = 24; - - } else { // Infinity and NaN's stay Infinity and NaN's - basetable[i | 0x000] = 0x7C00; - basetable[i | 0x100] = 0xFC00; - shifttable[i | 0x000] = 13; - shifttable[i | 0x100] = 13; - } - } - - fid.write("const quint32 qfloat16::basetable[512] = {\n"); - for (i = 0; i < 512; i++) - fid.write(PRINTHEX(basetable[i])); - - fid.write("};\n\n"); - - fid.write("const quint32 qfloat16::shifttable[512] = {\n"); - for (i = 0; i < 512; i++) - fid.write(PRINTHEX(shifttable[i])); - - fid.write("};\n\n"); - - fid.write("#endif // !__F16C__ && !__ARM_FP16_FORMAT_IEEE\n\n"); - fid.write("QT_END_NAMESPACE\n"); - fid.close(); - return 0; -} diff --git a/src/tools/qfloat16-tables/qfloat16-tables.pro b/src/tools/qfloat16-tables/qfloat16-tables.pro deleted file mode 100644 index a7d10ac197..0000000000 --- a/src/tools/qfloat16-tables/qfloat16-tables.pro +++ /dev/null @@ -1,9 +0,0 @@ -option(host_build) - -CONFIG += force_bootstrap -SOURCES += gen_qfloat16_tables.cpp - -load(qt_tool) - -lib.CONFIG = dummy_install -INSTALLS = lib diff --git a/src/tools/qlalr/cppgenerator.cpp b/src/tools/qlalr/cppgenerator.cpp index 508db696b1..95f70dc988 100644 --- a/src/tools/qlalr/cppgenerator.cpp +++ b/src/tools/qlalr/cppgenerator.cpp @@ -36,6 +36,8 @@ #include <QtCore/qfile.h> #include <QtCore/qmap.h> +#include <iterator> + namespace { void generateSeparator(int i, QTextStream &out) @@ -43,7 +45,7 @@ void generateSeparator(int i, QTextStream &out) if (!(i % 10)) { if (i) out << ","; - out << endl << " "; + out << Qt::endl << " "; } else { out << ", "; } @@ -126,9 +128,9 @@ QString CppGenerator::endIncludeGuard(const QString &fileName) void CppGenerator::operator () () { // action table... - state_count = aut.states.size (); - terminal_count = grammar.terminals.size (); - non_terminal_count = grammar.non_terminals.size (); + state_count = static_cast<int>(aut.states.size()); + terminal_count = static_cast<int>(grammar.terminals.size()); + non_terminal_count = static_cast<int>(grammar.non_terminals.size()); #define ACTION(i, j) table [(i) * terminal_count + (j)] #define GOTO(i, j) pgoto [(i) * non_terminal_count + (j)] @@ -156,7 +158,7 @@ void CppGenerator::operator () () if (grammar.isNonTerminal (a.key ())) { - Q_ASSERT (symbol >= terminal_count && symbol < grammar.names.size ()); + Q_ASSERT(symbol >= terminal_count && symbol < static_cast<int>(grammar.names.size())); GOTO (q, symbol - terminal_count) = r; } @@ -187,14 +189,14 @@ void CppGenerator::operator () () { if (verbose) qout() << "*** Warning. Found a reduce/reduce conflict in state " << q << " on token ``" << s << "'' between rule " - << r << " and " << -u << endl; + << r << " and " << -u << Qt::endl; ++reduce_reduce_conflict_count; u = qMax (u, -r); if (verbose) - qout() << "\tresolved using rule " << -u << endl; + qout() << "\tresolved using rule " << -u << Qt::endl; } else if (u > 0) @@ -227,7 +229,7 @@ void CppGenerator::operator () () ++shift_reduce_conflict_count; if (verbose) - qout() << "*** Warning. Found a shift/reduce conflict in state " << q << " on token ``" << s << "'' with rule " << r << endl; + qout() << "*** Warning. Found a shift/reduce conflict in state " << q << " on token ``" << s << "'' with rule " << r << Qt::endl; } } } @@ -238,14 +240,14 @@ void CppGenerator::operator () () { if (shift_reduce_conflict_count != grammar.expected_shift_reduce || reduce_reduce_conflict_count != grammar.expected_reduce_reduce) - qerr() << "*** Conflicts: " << shift_reduce_conflict_count << " shift/reduce, " << reduce_reduce_conflict_count << " reduce/reduce" << endl; + qerr() << "*** Conflicts: " << shift_reduce_conflict_count << " shift/reduce, " << reduce_reduce_conflict_count << " reduce/reduce" << Qt::endl; if (verbose) - qout() << endl << "*** Conflicts: " << shift_reduce_conflict_count << " shift/reduce, " << reduce_reduce_conflict_count << " reduce/reduce" << endl - << endl; + qout() << Qt::endl << "*** Conflicts: " << shift_reduce_conflict_count << " shift/reduce, " << reduce_reduce_conflict_count << " reduce/reduce" << Qt::endl + << Qt::endl; } - QBitArray used_rules (grammar.rules.count ()); + QBitArray used_rules{static_cast<int>(grammar.rules.size())}; int q = 0; for (StatePointer state = aut.states.begin (); state != aut.states.end (); ++state, ++q) @@ -259,14 +261,13 @@ void CppGenerator::operator () () } } - for (int i = 0; i < used_rules.count (); ++i) + auto rule = grammar.rules.begin(); + for (int i = 0; i < used_rules.count (); ++i, ++rule) { if (! used_rules.testBit (i)) { - RulePointer rule = grammar.rules.begin () + i; - if (rule != grammar.goal) - qerr() << "*** Warning: Rule ``" << *rule << "'' is useless!" << endl; + qerr() << "*** Warning: Rule ``" << *rule << "'' is useless!" << Qt::endl; } } @@ -280,7 +281,7 @@ void CppGenerator::operator () () if (u >= 0) continue; - RulePointer rule = grammar.rules.begin () + (- u - 1); + RulePointer rule = std::next(grammar.rules.begin(), - u - 1); if (state->defaultReduce == rule) u = 0; @@ -348,26 +349,26 @@ void CppGenerator::operator () () { out << copyrightHeader() << privateCopyrightHeader() - << endl; + << Qt::endl; } out << "// This file was generated by qlalr - DO NOT EDIT!\n"; - out << startIncludeGuard(grammar.merged_output) << endl; + out << startIncludeGuard(grammar.merged_output) << Qt::endl; if (copyright) { - out << "#if defined(ERROR)" << endl - << "# undef ERROR" << endl - << "#endif" << endl << endl; + out << "#if defined(ERROR)" << Qt::endl + << "# undef ERROR" << Qt::endl + << "#endif" << Qt::endl << Qt::endl; } generateDecl (out); generateImpl (out); out << p.decls(); out << p.impls(); - out << endl; + out << Qt::endl; - out << endIncludeGuard(grammar.merged_output) << endl; + out << endIncludeGuard(grammar.merged_output) << Qt::endl; return; } @@ -388,24 +389,24 @@ void CppGenerator::operator () () { out << copyrightHeader() << privateCopyrightHeader() - << endl; + << Qt::endl; } out << "// This file was generated by qlalr - DO NOT EDIT!\n"; - out << "#ifndef " << prot << endl - << "#define " << prot << endl - << endl; + out << "#ifndef " << prot << Qt::endl + << "#define " << prot << Qt::endl + << Qt::endl; if (copyright) { - out << "#include <QtCore/qglobal.h>" << endl << endl; - out << "QT_BEGIN_NAMESPACE" << endl << endl; + out << "#include <QtCore/qglobal.h>" << Qt::endl << Qt::endl; + out << "QT_BEGIN_NAMESPACE" << Qt::endl << Qt::endl; } generateDecl (out); if (copyright) - out << "QT_END_NAMESPACE" << endl; + out << "QT_END_NAMESPACE" << Qt::endl; - out << "#endif // " << prot << endl << endl; + out << "#endif // " << prot << Qt::endl << Qt::endl; } // end decls { // bits... @@ -419,12 +420,12 @@ void CppGenerator::operator () () out << "// This file was generated by qlalr - DO NOT EDIT!\n"; - out << "#include \"" << declFileName << "\"" << endl << endl; + out << "#include \"" << declFileName << "\"" << Qt::endl << Qt::endl; if (copyright) - out << "QT_BEGIN_NAMESPACE" << endl << endl; + out << "QT_BEGIN_NAMESPACE" << Qt::endl << Qt::endl; generateImpl(out); if (copyright) - out << "QT_END_NAMESPACE" << endl; + out << "QT_END_NAMESPACE" << Qt::endl; } // end bits @@ -455,10 +456,10 @@ QString CppGenerator::debugInfoProt() const void CppGenerator::generateDecl (QTextStream &out) { - out << "class " << grammar.table_name << endl - << "{" << endl - << "public:" << endl - << " enum VariousConstants {" << endl; + out << "class " << grammar.table_name << Qt::endl + << "{" << Qt::endl + << "public:" << Qt::endl + << " enum VariousConstants {" << Qt::endl; for (const Name &t : qAsConst(grammar.terminals)) { @@ -474,62 +475,62 @@ void CppGenerator::generateDecl (QTextStream &out) else name.prepend (grammar.token_prefix); - out << " " << name << " = " << value << "," << endl; + out << " " << name << " = " << value << "," << Qt::endl; } - out << endl - << " ACCEPT_STATE = " << accept_state << "," << endl - << " RULE_COUNT = " << grammar.rules.size () << "," << endl - << " STATE_COUNT = " << state_count << "," << endl - << " TERMINAL_COUNT = " << terminal_count << "," << endl - << " NON_TERMINAL_COUNT = " << non_terminal_count << "," << endl - << endl - << " GOTO_INDEX_OFFSET = " << compressed_action.index.size () << "," << endl - << " GOTO_INFO_OFFSET = " << compressed_action.info.size () << "," << endl - << " GOTO_CHECK_OFFSET = " << compressed_action.check.size () << endl - << " };" << endl - << endl - << " static const char *const spell[];" << endl - << " static const short lhs[];" << endl - << " static const short rhs[];" << endl; + out << Qt::endl + << " ACCEPT_STATE = " << accept_state << "," << Qt::endl + << " RULE_COUNT = " << grammar.rules.size () << "," << Qt::endl + << " STATE_COUNT = " << state_count << "," << Qt::endl + << " TERMINAL_COUNT = " << terminal_count << "," << Qt::endl + << " NON_TERMINAL_COUNT = " << non_terminal_count << "," << Qt::endl + << Qt::endl + << " GOTO_INDEX_OFFSET = " << compressed_action.index.size () << "," << Qt::endl + << " GOTO_INFO_OFFSET = " << compressed_action.info.size () << "," << Qt::endl + << " GOTO_CHECK_OFFSET = " << compressed_action.check.size () << Qt::endl + << " };" << Qt::endl + << Qt::endl + << " static const char *const spell[];" << Qt::endl + << " static const short lhs[];" << Qt::endl + << " static const short rhs[];" << Qt::endl; if (debug_info) { QString prot = debugInfoProt(); - out << endl << "#ifndef " << prot << endl - << " static const int rule_index[];" << endl - << " static const int rule_info[];" << endl - << "#endif // " << prot << endl << endl; + out << Qt::endl << "#ifndef " << prot << Qt::endl + << " static const int rule_index[];" << Qt::endl + << " static const int rule_info[];" << Qt::endl + << "#endif // " << prot << Qt::endl << Qt::endl; } - out << " static const short goto_default[];" << endl - << " static const short action_default[];" << endl - << " static const short action_index[];" << endl - << " static const short action_info[];" << endl - << " static const short action_check[];" << endl - << endl - << " static inline int nt_action (int state, int nt)" << endl - << " {" << endl - << " const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt;" << endl - << " if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt)" << endl - << " return goto_default [nt];" << endl - << endl - << " return action_info [GOTO_INFO_OFFSET + yyn];" << endl - << " }" << endl - << endl - << " static inline int t_action (int state, int token)" << endl - << " {" << endl - << " const int yyn = action_index [state] + token;" << endl - << endl - << " if (yyn < 0 || action_check [yyn] != token)" << endl - << " return - action_default [state];" << endl - << endl - << " return action_info [yyn];" << endl - << " }" << endl - << "};" << endl - << endl - << endl; + out << " static const short goto_default[];" << Qt::endl + << " static const short action_default[];" << Qt::endl + << " static const short action_index[];" << Qt::endl + << " static const short action_info[];" << Qt::endl + << " static const short action_check[];" << Qt::endl + << Qt::endl + << " static inline int nt_action (int state, int nt)" << Qt::endl + << " {" << Qt::endl + << " const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt;" << Qt::endl + << " if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt)" << Qt::endl + << " return goto_default [nt];" << Qt::endl + << Qt::endl + << " return action_info [GOTO_INFO_OFFSET + yyn];" << Qt::endl + << " }" << Qt::endl + << Qt::endl + << " static inline int t_action (int state, int token)" << Qt::endl + << " {" << Qt::endl + << " const int yyn = action_index [state] + token;" << Qt::endl + << Qt::endl + << " if (yyn < 0 || action_check [yyn] != token)" << Qt::endl + << " return - action_default [state];" << Qt::endl + << Qt::endl + << " return action_info [yyn];" << Qt::endl + << " }" << Qt::endl + << "};" << Qt::endl + << Qt::endl + << Qt::endl; } void CppGenerator::generateImpl (QTextStream &out) @@ -568,16 +569,16 @@ void CppGenerator::generateImpl (QTextStream &out) { first_nt = false; QString prot = debugInfoProt(); - out << endl << "#ifndef " << prot << endl; + out << Qt::endl << "#ifndef " << prot << Qt::endl; } out << "\"" << *t << "\""; } } if (debug_info) - out << endl << "#endif // " << debugInfoProt() << endl; + out << Qt::endl << "#endif // " << debugInfoProt() << Qt::endl; - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; out << "const short " << grammar.table_name << "::lhs [] = {"; idx = 0; @@ -587,7 +588,7 @@ void CppGenerator::generateImpl (QTextStream &out) out << aut.id (rule->lhs); } - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; out << "const short " << grammar.table_name << "::rhs [] = {"; idx = 0; @@ -597,13 +598,13 @@ void CppGenerator::generateImpl (QTextStream &out) out << rule->rhs.size (); } - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; if (debug_info) { QString prot = debugInfoProt(); - out << endl << "#ifndef " << prot << endl; + out << Qt::endl << "#ifndef " << prot << Qt::endl; out << "const int " << grammar.table_name << "::rule_info [] = {"; idx = 0; for (auto rule = grammar.rules.cbegin (); rule != grammar.rules.cend (); ++rule, ++idx) @@ -615,11 +616,11 @@ void CppGenerator::generateImpl (QTextStream &out) for (const Name &n : rule->rhs) out << ", " << name_ids.value (n); } - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; out << "const int " << grammar.table_name << "::rule_index [] = {"; idx = 0; - int offset = 0; + size_t offset = 0; for (RulePointer rule = grammar.rules.begin (); rule != grammar.rules.end (); ++rule, ++idx) { generateSeparator(idx, out); @@ -627,8 +628,8 @@ void CppGenerator::generateImpl (QTextStream &out) out << offset; offset += rule->rhs.size () + 1; } - out << endl << "};" << endl - << "#endif // " << prot << endl << endl; + out << Qt::endl << "};" << Qt::endl + << "#endif // " << prot << Qt::endl << Qt::endl; } out << "const short " << grammar.table_name << "::action_default [] = {"; @@ -642,27 +643,27 @@ void CppGenerator::generateImpl (QTextStream &out) else out << "0"; } - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; out << "const short " << grammar.table_name << "::goto_default [] = {"; generateList(defgoto, out); - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; out << "const short " << grammar.table_name << "::action_index [] = {"; generateList(compressed_action.index, out); - out << "," << endl; + out << "," << Qt::endl; generateList(compressed_goto.index, out); - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; out << "const short " << grammar.table_name << "::action_info [] = {"; generateList(compressed_action.info, out); - out << "," << endl; + out << "," << Qt::endl; generateList(compressed_goto.info, out); - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; out << "const short " << grammar.table_name << "::action_check [] = {"; generateList(compressed_action.check, out); - out << "," << endl; + out << "," << Qt::endl; generateList(compressed_goto.check, out); - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; } diff --git a/src/tools/qlalr/dotgraph.cpp b/src/tools/qlalr/dotgraph.cpp index 1fa0a1ac77..1d479af2b2 100644 --- a/src/tools/qlalr/dotgraph.cpp +++ b/src/tools/qlalr/dotgraph.cpp @@ -41,9 +41,9 @@ void DotGraph::operator () (Automaton *aut) { Grammar *g = aut->_M_grammar; - out << "digraph {" << endl << endl; + out << "digraph {" << Qt::endl << Qt::endl; - out << "subgraph Includes {" << endl; + out << "subgraph Includes {" << Qt::endl; for (Automaton::IncludesGraph::iterator incl = Automaton::IncludesGraph::begin_nodes (); incl != Automaton::IncludesGraph::end_nodes (); ++incl) { @@ -53,14 +53,14 @@ void DotGraph::operator () (Automaton *aut) out << "\t->\t"; out << "\"(" << aut->id ((*edge)->data.state) << ", " << (*edge)->data.nt << ")\"\t"; out << "[label=\"" << incl->data.state->follows [incl->data.nt] << "\"]"; - out << endl; + out << Qt::endl; } } - out << "}" << endl << endl; + out << "}" << Qt::endl << Qt::endl; - out << "subgraph LRA {" << endl; - //out << "node [shape=record];" << endl << endl; + out << "subgraph LRA {" << Qt::endl; + //out << "node [shape=record];" << Qt::endl << Qt::endl; for (StatePointer q = aut->states.begin (); q != aut->states.end (); ++q) { @@ -74,16 +74,16 @@ void DotGraph::operator () (Automaton *aut) for (ItemPointer item = q->kernel.begin (); item != q->kernel.end (); ++item) out << "| <" << index++ << "> " << *item; - out << "}\"]" << endl; + out << "}\"]" << Qt::endl; for (Bundle::iterator a = q->bundle.begin (); a != q->bundle.end (); ++a) { const char *clr = g->isTerminal (a.key ()) ? "blue" : "red"; - out << "\t" << state << "\t->\t" << aut->id (*a) << "\t[color=\"" << clr << "\",label=\"" << a.key () << "\"]" << endl; + out << "\t" << state << "\t->\t" << aut->id (*a) << "\t[color=\"" << clr << "\",label=\"" << a.key () << "\"]" << Qt::endl; } - out << endl; + out << Qt::endl; } - out << "}" << endl; - out << endl << endl << "}" << endl; + out << "}" << Qt::endl; + out << Qt::endl << Qt::endl << "}" << Qt::endl; } diff --git a/src/tools/qlalr/lalr.cpp b/src/tools/qlalr/lalr.cpp index ec960925aa..b9a9cf264f 100644 --- a/src/tools/qlalr/lalr.cpp +++ b/src/tools/qlalr/lalr.cpp @@ -51,7 +51,9 @@ QTextStream &qout() static QTextStream result(stdout, QIODevice::WriteOnly); return result; } +QT_END_NAMESPACE +namespace std { bool operator < (Name a, Name b) { return *a < *b; @@ -66,7 +68,7 @@ bool operator < (StatePointer a, StatePointer b) { return &*a < &*b; } -QT_END_NAMESPACE +} bool Read::operator < (const Read &other) const { @@ -313,7 +315,7 @@ void Automaton::buildNullables () } #ifndef QLALR_NO_DEBUG_NULLABLES - qerr() << "nullables = {" << nullables << endl; + qerr() << "nullables = {" << nullables << Qt::endl; #endif } @@ -329,7 +331,7 @@ QPair<StatePointer, bool> Automaton::internState (const State &state) struct _Bucket { - QLinkedList<ItemPointer> items; + std::list<ItemPointer> items; void insert (ItemPointer item) { items.push_back (item); } @@ -338,8 +340,8 @@ struct _Bucket { State st (aut->_M_grammar); - for (QLinkedList<ItemPointer>::iterator item = items.begin (); item != items.end (); ++item) - st.insert ((*item)->next ()); + for (auto &item : items) + st.insert(item->next()); return st; } @@ -456,7 +458,7 @@ void Automaton::buildLookbackSets () lookbacks.insert (item, Lookback (p, A)); #ifndef QLALR_NO_DEBUG_LOOKBACKS - qerr() << "*** (" << id (q) << ", " << *rule << ") lookback (" << id (p) << ", " << *A << ")" << endl; + qerr() << "*** (" << id (q) << ", " << *rule << ") lookback (" << id (p) << ", " << *A << ")" << Qt::endl; #endif } } @@ -487,7 +489,7 @@ void Automaton::buildDirectReads () #ifndef QLALR_NO_DEBUG_DIRECT_READS for (QMap<Name, NameSet>::iterator dr = q->reads.begin (); dr != q->reads.end (); ++dr) - qerr() << "*** DR(" << id (q) << ", " << dr.key () << ") = " << dr.value () << endl; + qerr() << "*** DR(" << id (q) << ", " << dr.key () << ") = " << dr.value () << Qt::endl; #endif } } @@ -520,7 +522,7 @@ void Automaton::buildReadsDigraph () dump (qerr(), source); qerr() << " reads "; dump (qerr(), target); - qerr() << endl; + qerr() << Qt::endl; #endif } } @@ -555,7 +557,7 @@ void Automaton::visitReadNode (ReadNode node) _M_reads_stack.push (node); #ifndef QLALR_NO_DEBUG_INCLUDES - // qerr() << "*** Debug. visit node (" << id (node->data.state) << ", " << node->data.nt << ") N = " << N << endl; + // qerr() << "*** Debug. visit node (" << id (node->data.state) << ", " << node->data.nt << ") N = " << N << Qt::endl; #endif for (ReadsGraph::edge_iterator edge = node->begin (); edge != node->end (); ++edge) @@ -635,7 +637,7 @@ void Automaton::buildIncludesDigraph () source->insertEdge (target); #ifndef QLALR_NO_DEBUG_INCLUDES - qerr() << "*** (" << id (p) << ", " << *A << ") includes (" << id (pp) << ", " << *name << ")" << endl; + qerr() << "*** (" << id (p) << ", " << *A << ") includes (" << id (pp) << ", " << *name << ")" << Qt::endl; #endif // QLALR_NO_DEBUG_INCLUDES continue; @@ -657,7 +659,7 @@ void Automaton::buildIncludesDigraph () source->insertEdge (target); #ifndef QLALR_NO_DEBUG_INCLUDES - qerr() << "*** (" << id (p) << ", " << *A << ") includes (" << id (pp) << ", " << *name << ")" << endl; + qerr() << "*** (" << id (p) << ", " << *A << ") includes (" << id (pp) << ", " << *name << ")" << Qt::endl; #endif // QLALR_NO_DEBUG_INCLUDES } } @@ -674,7 +676,7 @@ void Automaton::visitIncludeNode (IncludeNode node) _M_includes_stack.push (node); #ifndef QLALR_NO_DEBUG_INCLUDES - // qerr() << "*** Debug. visit node (" << id (node->data.state) << ", " << node->data.nt << ") N = " << N << endl; + // qerr() << "*** Debug. visit node (" << id (node->data.state) << ", " << node->data.nt << ") N = " << N << Qt::endl; #endif for (IncludesGraph::edge_iterator edge = node->begin (); edge != node->end (); ++edge) @@ -690,7 +692,7 @@ void Automaton::visitIncludeNode (IncludeNode node) dump (qerr(), node); qerr() << " += follows"; dump (qerr(), r); - qerr() << endl; + qerr() << Qt::endl; #endif NameSet &dst = node->data.state->follows [node->data.nt]; @@ -726,7 +728,7 @@ void Automaton::buildLookaheads () #ifndef QLALR_NO_DEBUG_LOOKAHEADS qerr() << "(" << id (p) << ", " << *item->rule << ") lookbacks "; dump (qerr(), lookback); - qerr() << " with follows (" << id (q) << ", " << lookback.nt << ") = " << q->follows [lookback.nt] << endl; + qerr() << " with follows (" << id (q) << ", " << lookback.nt << ") = " << q->follows [lookback.nt] << Qt::endl; #endif lookaheads [item].insert (q->follows [lookback.nt].begin (), q->follows [lookback.nt].end ()); @@ -754,7 +756,7 @@ void Automaton::buildDefaultReduceActions () if (item->dot != item->end_rhs ()) continue; - int la = lookaheads.value (item).size (); + int la = static_cast<int>(lookaheads.value(item).size()); if (def == state->closure.end () || la > size) { def = item; diff --git a/src/tools/qlalr/lalr.g b/src/tools/qlalr/lalr.g index 05d30c21fd..a849800dd5 100644 --- a/src/tools/qlalr/lalr.g +++ b/src/tools/qlalr/lalr.g @@ -261,7 +261,7 @@ int Recognizer::nextToken() if (ch == QLatin1Char ('"')) inp (); else - qerr() << _M_input_file << ":" << _M_line << ": Warning. Expected `\"'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Warning. Expected `\"'" << Qt::endl; _M_current_value = text; return (token = STRING_LITERAL); @@ -314,7 +314,7 @@ int Recognizer::nextToken() return (token = PREC); else { - qerr() << _M_input_file << ":" << _M_line << ": Unknown keyword `" << text << "'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Unknown keyword `" << text << "'" << Qt::endl; exit (EXIT_FAILURE); return (token = ERROR); } @@ -659,7 +659,7 @@ case $rule_number: { if (_M_grammar->terminals.find (_M_current_rule->lhs) != _M_grammar->terminals.end ()) { - qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << Qt::endl; return false; } @@ -683,7 +683,7 @@ case $rule_number: { if (_M_grammar->terminals.find (_M_current_rule->lhs) != _M_grammar->terminals.end ()) { - qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << Qt::endl; return false; } @@ -712,7 +712,7 @@ case $rule_number: { Name tok = _M_grammar->intern (sym(2)); if (! _M_grammar->isTerminal (tok)) { - qerr() << _M_input_file << ":" << _M_line << ": `" << *tok << " is not a terminal symbol" << endl; + qerr() << _M_input_file << ":" << _M_line << ": `" << *tok << " is not a terminal symbol" << Qt::endl; _M_current_rule->prec = _M_grammar->names.end (); } else @@ -758,7 +758,7 @@ case $rule_number: { } } - qerr() << _M_input_file << ":" << _M_line << ": Syntax error" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Syntax error" << Qt::endl; return false; } diff --git a/src/tools/qlalr/lalr.h b/src/tools/qlalr/lalr.h index 8eadee400d..473ea89769 100644 --- a/src/tools/qlalr/lalr.h +++ b/src/tools/qlalr/lalr.h @@ -39,6 +39,7 @@ #include <algorithm> #include <functional> +#include <set> class Rule; class State; @@ -48,121 +49,24 @@ class State; class Arrow; class Automaton; -template <typename _Tp > -class OrderedSet : protected QMap<_Tp, bool> -{ - typedef QMap<_Tp, bool> _Base; - -public: - class const_iterator - { - typename _Base::const_iterator _M_iterator; - - public: - const_iterator () {} - - const_iterator (const typename _Base::iterator &it): - _M_iterator (typename _Base::const_iterator(it)) {} - const_iterator (const typename _Base::const_iterator &it): - _M_iterator (it) {} - - const _Tp &operator * () const - { return _M_iterator.key (); } - - const _Tp *operator -> () const - { return &_M_iterator.key (); } - - const_iterator &operator ++ () - { ++_M_iterator; return *this; } - - const_iterator operator ++ (int) const - { - const_iterator me (*this); - ++_M_iterator; - return me; - } - - bool operator == (const const_iterator &other) const - { return _M_iterator == other._M_iterator; } - - bool operator != (const const_iterator &other) const - { return _M_iterator != other._M_iterator; } - }; - - typedef const_iterator iterator; - -public: - OrderedSet () {} - - const_iterator begin () const - { return const_iterator (_Base::begin ()); } - - const_iterator end () const - { return const_iterator (_Base::end ()); } - - bool isEmpty () const - { return _Base::isEmpty (); } - - int size () const - { return _Base::size (); } - - const_iterator find (const _Tp &elt) const - { return const_iterator (_Base::find (elt)); } - - QPair<const_iterator, bool> insert (const _Tp &elt) - { - int elts = _Base::size (); - const_iterator it (_Base::insert (typename _Base::key_type (elt), true)); - return qMakePair (it, elts != _Base::size ()); - } - - QPair<const_iterator, bool> insert (const_iterator, const _Tp &elt) - { - int elts = _Base::size (); - const_iterator it (_Base::insert (typename _Base::key_type (elt), true)); - return qMakePair (it, elts != _Base::size ()); - } - - const _Tp &operator [] (const _Tp &elt) - { return *insert (elt)->first; } - - template <typename _InputIterator> - void insert (_InputIterator first, _InputIterator last) - { - for (; first != last; ++first) - insert (*first); - } -}; // names -typedef QLinkedList<QString>::iterator Name; -QT_BEGIN_NAMESPACE -Q_DECLARE_TYPEINFO(QLinkedList<QString>::iterator, Q_PRIMITIVE_TYPE); -QT_END_NAMESPACE -typedef QLinkedList<Name> NameList; -typedef OrderedSet<Name> NameSet; +typedef std::list<QString>::iterator Name; +typedef std::list<Name> NameList; +typedef std::set<Name> NameSet; // items -typedef QLinkedList<Item> ItemList; +typedef std::list<Item> ItemList; typedef ItemList::iterator ItemPointer; -QT_BEGIN_NAMESPACE -Q_DECLARE_TYPEINFO(ItemList::iterator, Q_PRIMITIVE_TYPE); -QT_END_NAMESPACE // rules -typedef QLinkedList<Rule> debug_infot; +typedef std::list<Rule> debug_infot; typedef debug_infot::iterator RulePointer; -QT_BEGIN_NAMESPACE -Q_DECLARE_TYPEINFO(debug_infot::iterator, Q_PRIMITIVE_TYPE); -QT_END_NAMESPACE typedef QMultiMap<Name, RulePointer> RuleMap; // states -typedef QLinkedList<State> StateList; +typedef std::list<State> StateList; typedef StateList::iterator StatePointer; -QT_BEGIN_NAMESPACE -Q_DECLARE_TYPEINFO(StateList::iterator, Q_PRIMITIVE_TYPE); -QT_END_NAMESPACE // arrows typedef QMap<Name, StatePointer> Bundle; @@ -257,9 +161,9 @@ template <typename _Tp> class Node { public: - typedef OrderedSet<Node<_Tp> > Repository; + typedef std::set<Node<_Tp> > Repository; typedef typename Repository::iterator iterator; - typedef typename QLinkedList<iterator>::iterator edge_iterator; + typedef typename std::list<iterator>::iterator edge_iterator; public: static iterator get (_Tp data); @@ -297,7 +201,7 @@ public: // attributes mutable bool root; mutable int dfn; mutable _Tp data; - mutable QLinkedList<iterator> outs; + mutable std::list<iterator> outs; protected: inline Node () {} @@ -319,7 +223,7 @@ typename Node<_Tp>::iterator Node<_Tp>::get (_Tp data) } template <typename _Tp> -QPair<typename QLinkedList<typename Node<_Tp>::iterator>::iterator, bool> Node<_Tp>::insertEdge (typename Node<_Tp>::iterator other) const +QPair<typename std::list<typename Node<_Tp>::iterator>::iterator, bool> Node<_Tp>::insertEdge(typename Node<_Tp>::iterator other) const { edge_iterator it = std::find (outs.begin (), outs.end (), other); @@ -356,7 +260,7 @@ public: QString decl_file_name; QString impl_file_name; QString token_prefix; - QLinkedList<QString> names; + std::list<QString> names; Name start; NameSet terminals; NameSet non_terminals; @@ -406,9 +310,6 @@ public: StatePointer state; Name nt; }; -QT_BEGIN_NAMESPACE -Q_DECLARE_TYPEINFO(OrderedSet<Node<Read> >::const_iterator, Q_PRIMITIVE_TYPE); -QT_END_NAMESPACE class Include { @@ -430,9 +331,6 @@ public: StatePointer state; Name nt; }; -QT_BEGIN_NAMESPACE -Q_DECLARE_TYPEINFO(OrderedSet<Node<Include> >::const_iterator, Q_PRIMITIVE_TYPE); -QT_END_NAMESPACE class Automaton { @@ -491,11 +389,11 @@ private: int _M_includes_dfn; }; -QT_BEGIN_NAMESPACE +namespace std { bool operator < (Name a, Name b); bool operator < (StatePointer a, StatePointer b); bool operator < (ItemPointer a, ItemPointer b); -QT_END_NAMESPACE +} QTextStream &operator << (QTextStream &out, const Name &n); QTextStream &operator << (QTextStream &out, const Rule &r); diff --git a/src/tools/qlalr/main.cpp b/src/tools/qlalr/main.cpp index 5971eb201d..6a57c7aa7a 100644 --- a/src/tools/qlalr/main.cpp +++ b/src/tools/qlalr/main.cpp @@ -44,15 +44,15 @@ static void help_me () { - qerr() << "Usage: qlalr [options] [input file name]" << endl - << endl - << " --help, -h\t\tdisplay this help and exit" << endl - << " --verbose, -v\t\tverbose output" << endl - << " --no-debug\t\tno debug information" << endl - << " --no-lines\t\tno #line directives" << endl - << " --dot\t\t\tgenerate a graph" << endl - << " --qt\t\tadd the Qt copyright header and Qt-specific types and macros" << endl - << endl; + qerr() << "Usage: qlalr [options] [input file name]" << Qt::endl + << Qt::endl + << " --help, -h\t\tdisplay this help and exit" << Qt::endl + << " --verbose, -v\t\tverbose output" << Qt::endl + << " --no-debug\t\tno debug information" << Qt::endl + << " --no-lines\t\tno #line directives" << Qt::endl + << " --dot\t\t\tgenerate a graph" << Qt::endl + << " --qt\t\tadd the Qt copyright header and Qt-specific types and macros" << Qt::endl + << Qt::endl; exit (0); } @@ -91,7 +91,7 @@ int main (int argc, char *argv[]) file_name = arg; else - qerr() << "*** Warning. Ignore argument `" << arg << "'" << endl; + qerr() << "*** Warning. Ignore argument `" << arg << "'" << Qt::endl; } if (file_name.isEmpty ()) @@ -106,15 +106,15 @@ int main (int argc, char *argv[]) if (! p.parse (file_name)) exit (EXIT_FAILURE); - if (grammar.rules.isEmpty ()) + if (grammar.rules.empty()) { - qerr() << "*** Fatal. No rules!" << endl; + qerr() << "*** Fatal. No rules!" << Qt::endl; exit (EXIT_FAILURE); } else if (grammar.start == grammar.names.end ()) { - qerr() << "*** Fatal. No start symbol!" << endl; + qerr() << "*** Fatal. No start symbol!" << Qt::endl; exit (EXIT_FAILURE); } diff --git a/src/tools/qlalr/parsetable.cpp b/src/tools/qlalr/parsetable.cpp index c88ac1291e..9e71acebb4 100644 --- a/src/tools/qlalr/parsetable.cpp +++ b/src/tools/qlalr/parsetable.cpp @@ -43,13 +43,13 @@ void ParseTable::operator () (Automaton *aut) int rindex = 1; for (RulePointer rule = g->rules.begin (); rule != g->rules.end (); ++rule) - out << rindex++ << ")\t" << *rule << endl; - out << endl << endl; + out << rindex++ << ")\t" << *rule << Qt::endl; + out << Qt::endl << Qt::endl; int index = 0; for (StatePointer state = aut->states.begin (); state != aut->states.end (); ++state) { - out << "state " << index++ << endl << endl; + out << "state " << index++ << Qt::endl << Qt::endl; for (ItemPointer item = state->kernel.begin (); item != state->kernel.end (); ++item) { @@ -58,7 +58,7 @@ void ParseTable::operator () (Automaton *aut) if (item->dot == item->end_rhs ()) out << " " << aut->lookaheads [item]; - out << endl; + out << Qt::endl; } bool first = true; @@ -68,11 +68,11 @@ void ParseTable::operator () (Automaton *aut) continue; if (first) - out << endl; + out << Qt::endl; first = false; - out << " " << *arrow.key () << " shift, and go to state " << std::distance (aut->states.begin (), *arrow) << endl; + out << " " << *arrow.key () << " shift, and go to state " << std::distance (aut->states.begin (), *arrow) << Qt::endl; } first = true; @@ -82,13 +82,13 @@ void ParseTable::operator () (Automaton *aut) continue; if (first) - out << endl; + out << Qt::endl; first = false; const auto lookaheads = aut->lookaheads.value(item); for (const Name &la : lookaheads) - out << " " << *la << " reduce using rule " << aut->id (item->rule) << " (" << *item->rule->lhs << ")" << endl; + out << " " << *la << " reduce using rule " << aut->id (item->rule) << " (" << *item->rule->lhs << ")" << Qt::endl; } first = true; @@ -98,19 +98,19 @@ void ParseTable::operator () (Automaton *aut) continue; if (first) - out << endl; + out << Qt::endl; first = false; - out << " " << *arrow.key () << " go to state " << std::distance (aut->states.begin (), *arrow) << endl; + out << " " << *arrow.key () << " go to state " << std::distance (aut->states.begin (), *arrow) << Qt::endl; } if (state->defaultReduce != g->rules.end ()) { - out << endl - << " $default reduce using rule " << aut->id (state->defaultReduce) << " (" << *state->defaultReduce->lhs << ")" << endl; + out << Qt::endl + << " $default reduce using rule " << aut->id (state->defaultReduce) << " (" << *state->defaultReduce->lhs << ")" << Qt::endl; } - out << endl; + out << Qt::endl; } } diff --git a/src/tools/qlalr/recognizer.cpp b/src/tools/qlalr/recognizer.cpp index ab797c85d0..3da54c0c6a 100644 --- a/src/tools/qlalr/recognizer.cpp +++ b/src/tools/qlalr/recognizer.cpp @@ -97,7 +97,7 @@ int Recognizer::nextToken() if (ch == QLatin1Char ('"')) inp (); else - qerr() << _M_input_file << ":" << _M_line << ": Warning. Expected `\"'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Warning. Expected `\"'" << Qt::endl; _M_current_value = text; return (token = STRING_LITERAL); @@ -150,7 +150,7 @@ int Recognizer::nextToken() return (token = PREC); else { - qerr() << _M_input_file << ":" << _M_line << ": Unknown keyword `" << text << "'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Unknown keyword `" << text << "'" << Qt::endl; exit (EXIT_FAILURE); return (token = ERROR); } @@ -405,7 +405,7 @@ case 34: { if (_M_grammar->terminals.find (_M_current_rule->lhs) != _M_grammar->terminals.end ()) { - qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << Qt::endl; return false; } @@ -420,7 +420,7 @@ case 38: { if (_M_grammar->terminals.find (_M_current_rule->lhs) != _M_grammar->terminals.end ()) { - qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << Qt::endl; return false; } @@ -443,7 +443,7 @@ case 40: { Name tok = _M_grammar->intern (sym(2)); if (! _M_grammar->isTerminal (tok)) { - qerr() << _M_input_file << ":" << _M_line << ": `" << *tok << " is not a terminal symbol" << endl; + qerr() << _M_input_file << ":" << _M_line << ": `" << *tok << " is not a terminal symbol" << Qt::endl; _M_current_rule->prec = _M_grammar->names.end (); } else @@ -474,7 +474,7 @@ case 43: { } } - qerr() << _M_input_file << ":" << _M_line << ": Syntax error" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Syntax error" << Qt::endl; return false; } diff --git a/src/tools/qvkgen/qvkgen.cpp b/src/tools/qvkgen/qvkgen.cpp index 059f9413cb..4db3f26161 100644 --- a/src/tools/qvkgen/qvkgen.cpp +++ b/src/tools/qvkgen/qvkgen.cpp @@ -192,22 +192,20 @@ QString VkSpecParser::parseName() QString funcSig(const VkSpecParser::Command &c, const char *className = nullptr) { - QString s; - s.sprintf("%s %s%s%s", qPrintable(c.cmd.type), - (className ? className : ""), (className ? "::" : ""), - qPrintable(c.cmd.name)); + QString s(QString::asprintf("%s %s%s%s", qPrintable(c.cmd.type), + (className ? className : ""), (className ? "::" : ""), + qPrintable(c.cmd.name))); if (!c.args.isEmpty()) { s += QLatin1Char('('); bool first = true; for (const VkSpecParser::TypedName &a : c.args) { - QString argStr; - argStr.sprintf("%s%s%s%s", qPrintable(a.type), (a.type.endsWith(QLatin1Char('*')) ? "" : " "), - qPrintable(a.name), qPrintable(a.typeSuffix)); if (!first) s += QStringLiteral(", "); else first = false; - s += argStr; + s += QString::asprintf("%s%s%s%s", qPrintable(a.type), + (a.type.endsWith(QLatin1Char('*')) ? "" : " "), + qPrintable(a.name), qPrintable(a.typeSuffix)); } s += QLatin1Char(')'); } @@ -216,13 +214,12 @@ QString funcSig(const VkSpecParser::Command &c, const char *className = nullptr) QString funcCall(const VkSpecParser::Command &c, int idx) { - QString s; // template: // [return] reinterpret_cast<PFN_vkEnumeratePhysicalDevices>(d_ptr->m_funcs[0])(instance, pPhysicalDeviceCount, pPhysicalDevices); - s.sprintf("%sreinterpret_cast<PFN_%s>(d_ptr->m_funcs[%d])", - (c.cmd.type == QStringLiteral("void") ? "" : "return "), - qPrintable(c.cmd.name), - idx); + QString s = QString::asprintf("%sreinterpret_cast<PFN_%s>(d_ptr->m_funcs[%d])", + (c.cmd.type == QStringLiteral("void") ? "" : "return "), + qPrintable(c.cmd.name), + idx); if (!c.args.isEmpty()) { s += QLatin1Char('('); bool first = true; @@ -338,10 +335,9 @@ bool genVulkanFunctionsH(const QVector<VkSpecParser::Command> &commands, const Q *dst += QStringLiteral(";\n"); } - QString str; - str.sprintf(s, preamble.get(licHeaderFn).constData(), instCmdStr.toUtf8().constData(), devCmdStr.toUtf8().constData()); - - f.write(str.toUtf8()); + f.write(QString::asprintf(s, preamble.get(licHeaderFn).constData(), + instCmdStr.toUtf8().constData(), + devCmdStr.toUtf8().constData()).toUtf8()); return true; } @@ -400,10 +396,7 @@ bool genVulkanFunctionsPH(const QVector<VkSpecParser::Command> &commands, const [](const VkSpecParser::Command &c) { return c.deviceLevel; }); const int instLevelCount = commands.count() - devLevelCount; - QString str; - str.sprintf(s, preamble.get(licHeaderFn).constData(), instLevelCount, devLevelCount); - - f.write(str.toUtf8()); + f.write(QString::asprintf(s, preamble.get(licHeaderFn).constData(), instLevelCount, devLevelCount).toUtf8()); return true; } @@ -478,10 +471,12 @@ bool genVulkanFunctionsPC(const QVector<VkSpecParser::Command> &commands, const if (instCmdNamesStr.count() > 2) instCmdNamesStr = instCmdNamesStr.left(instCmdNamesStr.count() - 2); - QString str; - str.sprintf(s, preamble.get(licHeaderFn).constData(), - instCmdWrapperStr.toUtf8().constData(), instCmdNamesStr.toUtf8().constData(), instIdx, - devCmdWrapperStr.toUtf8().constData(), devCmdNamesStr.toUtf8().constData(), commands.count() - instIdx); + const QString str = + QString::asprintf(s, preamble.get(licHeaderFn).constData(), + instCmdWrapperStr.toUtf8().constData(), + instCmdNamesStr.toUtf8().constData(), instIdx, + devCmdWrapperStr.toUtf8().constData(), + devCmdNamesStr.toUtf8().constData(), commands.count() - instIdx); f.write(str.toUtf8()); diff --git a/src/tools/rcc/main.cpp b/src/tools/rcc/main.cpp index 6e8c13be15..ac87e48e39 100644 --- a/src/tools/rcc/main.cpp +++ b/src/tools/rcc/main.cpp @@ -99,6 +99,37 @@ int createProject(const QString &outFileName) return 0; } +// Escapes a path for use in a Depfile (Makefile syntax) +QString makefileEscape(const QString &filepath) +{ + // Always use forward slashes + QString result = QDir::cleanPath(filepath); + // Spaces are escaped with a backslash + result.replace(QLatin1Char(' '), QLatin1String("\\ ")); + // Pipes are escaped with a backslash + result.replace(QLatin1Char('|'), QLatin1String("\\|")); + // Dollars are escaped with a dollar + result.replace(QLatin1Char('$'), QLatin1String("$$")); + + return result; +} + +void writeDepFile(QIODevice &iodev, const QStringList &depsList, const QString &targetName) +{ + QTextStream out(&iodev); + out << qPrintable(makefileEscape(targetName)); + out << QLatin1Char(':'); + + // Write depfile + for (int i = 0; i < depsList.size(); ++i) { + out << QLatin1Char(' '); + + out << qPrintable(makefileEscape(depsList.at(i))); + } + + out << QLatin1Char('\n'); +} + int runRcc(int argc, char *argv[]) { QCoreApplication app(argc, argv); @@ -155,6 +186,11 @@ int runRcc(int argc, char *argv[]) QCommandLineOption binaryOption(QStringLiteral("binary"), QStringLiteral("Output a binary file for use as a dynamic resource.")); parser.addOption(binaryOption); + QCommandLineOption generatorOption(QStringList{QStringLiteral("g"), QStringLiteral("generator")}); + generatorOption.setDescription(QStringLiteral("Select generator.")); + generatorOption.setValueName(QStringLiteral("cpp|python|python2")); + parser.addOption(generatorOption); + QCommandLineOption passOption(QStringLiteral("pass"), QStringLiteral("Pass number for big resources"), QStringLiteral("number")); parser.addOption(passOption); @@ -171,6 +207,10 @@ int runRcc(int argc, char *argv[]) QStringLiteral("Only output a mapping of resource paths to file system paths defined in the .qrc file, do not generate code.")); parser.addOption(mapOption); + QCommandLineOption depFileOption(QStringList{QStringLiteral("d"), QStringLiteral("depfile")}, + QStringLiteral("Write a depfile with the .qrc dependencies to <file>."), QStringLiteral("file")); + parser.addOption(depFileOption); + QCommandLineOption projectOption(QStringLiteral("project"), QStringLiteral("Output a resource file containing all files from the current directory.")); parser.addOption(projectOption); @@ -220,6 +260,18 @@ int runRcc(int argc, char *argv[]) library.setCompressThreshold(parser.value(thresholdOption).toInt()); if (parser.isSet(binaryOption)) library.setFormat(RCCResourceLibrary::Binary); + if (parser.isSet(generatorOption)) { + auto value = parser.value(generatorOption); + if (value == QLatin1String("cpp")) + library.setFormat(RCCResourceLibrary::C_Code); + else if (value == QLatin1String("python")) + library.setFormat(RCCResourceLibrary::Python3_Code); + else if (value == QLatin1String("python2")) + library.setFormat(RCCResourceLibrary::Python2_Code); + else + errorMsg = QLatin1String("Invalid generator: ") + value; + } + if (parser.isSet(passOption)) { if (parser.value(passOption) == QLatin1String("1")) library.setFormat(RCCResourceLibrary::Pass1); @@ -249,6 +301,7 @@ int runRcc(int argc, char *argv[]) QString outFilename = parser.value(outputOption); QString tempFilename = parser.value(tempOption); + QString depFilename = parser.value(depFileOption); if (projectRequested) { return createProject(outFilename); @@ -280,6 +333,8 @@ int runRcc(int argc, char *argv[]) switch (library.format()) { case RCCResourceLibrary::C_Code: case RCCResourceLibrary::Pass1: + case RCCResourceLibrary::Python3_Code: + case RCCResourceLibrary::Python2_Code: mode = QIODevice::WriteOnly | QIODevice::Text; break; case RCCResourceLibrary::Pass2: @@ -333,6 +388,28 @@ int runRcc(int argc, char *argv[]) return 0; } + // Write depfile + if (!depFilename.isEmpty()) { + QFile depout; + depout.setFileName(depFilename); + + if (outFilename.isEmpty() || outFilename == QLatin1String("-")) { + const QString msg = QString::fromUtf8("Unable to write depfile when outputting to stdout!\n"); + errorDevice.write(msg.toUtf8()); + return 1; + } + + if (!depout.open(QIODevice::WriteOnly | QIODevice::Text)) { + const QString msg = QString::fromUtf8("Unable to open depfile %1 for writing: %2\n") + .arg(depout.fileName(), depout.errorString()); + errorDevice.write(msg.toUtf8()); + return 1; + } + + writeDepFile(depout, library.dataFiles(), outFilename); + depout.close(); + } + QFile temp; if (!tempFilename.isEmpty()) { temp.setFileName(tempFilename); diff --git a/src/tools/rcc/rcc.cpp b/src/tools/rcc/rcc.cpp index 011a7db810..9acbce25ff 100644 --- a/src/tools/rcc/rcc.cpp +++ b/src/tools/rcc/rcc.cpp @@ -37,6 +37,7 @@ #include <qfile.h> #include <qiodevice.h> #include <qlocale.h> +#include <qregexp.h> #include <qstack.h> #include <qxmlstream.h> @@ -66,11 +67,8 @@ enum { # define CONSTANT_COMPRESSALGO_DEFAULT RCCResourceLibrary::CompressionAlgorithm::None #endif -#define writeString(s) write(s, sizeof(s)) - void RCCResourceLibrary::write(const char *str, int len) { - --len; // trailing \0 on string literals... int n = m_out.size(); m_out.resize(n + len); memcpy(m_out.data() + n, str, len); @@ -176,6 +174,8 @@ void RCCFileInfo::writeDataInfo(RCCResourceLibrary &lib) { const bool text = lib.m_format == RCCResourceLibrary::C_Code; const bool pass1 = lib.m_format == RCCResourceLibrary::Pass1; + const bool python = lib.m_format == RCCResourceLibrary::Python3_Code + || lib.m_format == RCCResourceLibrary::Python2_Code; //some info if (text || pass1) { if (m_language != QLocale::C) { @@ -222,6 +222,8 @@ void RCCFileInfo::writeDataInfo(RCCResourceLibrary &lib) } if (text || pass1) lib.writeChar('\n'); + else if (python) + lib.writeString("\\\n"); if (lib.formatVersion() >= 2) { // last modified time stamp @@ -236,6 +238,8 @@ void RCCFileInfo::writeDataInfo(RCCResourceLibrary &lib) lib.writeNumber8(lastmod); if (text || pass1) lib.writeChar('\n'); + else if (python) + lib.writeString("\\\n"); } } @@ -246,6 +250,8 @@ qint64 RCCFileInfo::writeDataBlob(RCCResourceLibrary &lib, qint64 offset, const bool pass1 = lib.m_format == RCCResourceLibrary::Pass1; const bool pass2 = lib.m_format == RCCResourceLibrary::Pass2; const bool binary = lib.m_format == RCCResourceLibrary::Binary; + const bool python = lib.m_format == RCCResourceLibrary::Python3_Code + || lib.m_format == RCCResourceLibrary::Python2_Code; //capture the offset m_dataOffset = offset; @@ -343,20 +349,24 @@ qint64 RCCFileInfo::writeDataBlob(RCCResourceLibrary &lib, qint64 offset, } // write the length - - if (text || binary || pass2) + if (text || binary || pass2 || python) lib.writeNumber4(data.size()); if (text || pass1) lib.writeString("\n "); + else if (python) + lib.writeString("\\\n"); offset += 4; // write the payload const char *p = data.constData(); - if (text) { + if (text || python) { for (int i = data.size(), j = 0; --i >= 0; --j) { lib.writeHex(*p++); if (j == 0) { - lib.writeString("\n "); + if (text) + lib.writeString("\n "); + else + lib.writeString("\\\n"); j = 16; } } @@ -368,6 +378,9 @@ qint64 RCCFileInfo::writeDataBlob(RCCResourceLibrary &lib, qint64 offset, // done if (text || pass1) lib.writeString("\n "); + else if (python) + lib.writeString("\\\n"); + return offset; } @@ -375,6 +388,8 @@ qint64 RCCFileInfo::writeDataName(RCCResourceLibrary &lib, qint64 offset) { const bool text = lib.m_format == RCCResourceLibrary::C_Code; const bool pass1 = lib.m_format == RCCResourceLibrary::Pass1; + const bool python = lib.m_format == RCCResourceLibrary::Python3_Code + || lib.m_format == RCCResourceLibrary::Python2_Code; // capture the offset m_nameOffset = offset; @@ -390,12 +405,16 @@ qint64 RCCFileInfo::writeDataName(RCCResourceLibrary &lib, qint64 offset) lib.writeNumber2(m_name.length()); if (text || pass1) lib.writeString("\n "); + else if (python) + lib.writeString("\\\n"); offset += 2; // write the hash lib.writeNumber4(qt_hash(m_name)); if (text || pass1) lib.writeString("\n "); + else if (python) + lib.writeString("\\\n"); offset += 4; // write the m_name @@ -404,12 +423,17 @@ qint64 RCCFileInfo::writeDataName(RCCResourceLibrary &lib, qint64 offset) lib.writeNumber2(unicode[i].unicode()); if ((text || pass1) && i % 16 == 0) lib.writeString("\n "); + else if (python && i % 16 == 0) + lib.writeString("\\\n"); } offset += m_name.length()*2; // done if (text || pass1) lib.writeString("\n "); + else if (python) + lib.writeString("\\\n"); + return offset; } @@ -956,21 +980,40 @@ void RCCResourceLibrary::writeDecimal(int value) Q_ASSERT(m_format != RCCResourceLibrary::Binary); char buf[std::numeric_limits<int>::digits10 + 2]; int n = snprintf(buf, sizeof(buf), "%d", value); - write(buf, n + 1); // write() takes a size including terminating NUL + write(buf, n); +} + +static const char hexDigits[] = "0123456789abcdef"; + +inline void RCCResourceLibrary::write2HexDigits(quint8 number) +{ + writeChar(hexDigits[number >> 4]); + writeChar(hexDigits[number & 0xf]); } void RCCResourceLibrary::writeHex(quint8 tmp) { - const char digits[] = "0123456789abcdef"; - writeChar('0'); - writeChar('x'); - if (tmp < 16) { - writeChar(digits[tmp]); - } else { - writeChar(digits[tmp >> 4]); - writeChar(digits[tmp & 0xf]); + switch (m_format) { + case RCCResourceLibrary::Python3_Code: + case RCCResourceLibrary::Python2_Code: + if (tmp >= 32 && tmp < 127 && tmp != '"' && tmp != '\\') { + writeChar(char(tmp)); + } else { + writeChar('\\'); + writeChar('x'); + write2HexDigits(tmp); + } + break; + default: + writeChar('0'); + writeChar('x'); + if (tmp < 16) + writeChar(hexDigits[tmp]); + else + write2HexDigits(tmp); + writeChar(','); + break; } - writeChar(','); } void RCCResourceLibrary::writeNumber2(quint16 number) @@ -1038,7 +1081,9 @@ void RCCResourceLibrary::writeNumber8(quint64 number) bool RCCResourceLibrary::writeHeader() { - if (m_format == C_Code || m_format == Pass1) { + switch (m_format) { + case C_Code: + case Pass1: writeString("/****************************************************************************\n"); writeString("** Resource object code\n"); writeString("**\n"); @@ -1047,7 +1092,20 @@ bool RCCResourceLibrary::writeHeader() writeString("\n**\n"); writeString("** WARNING! All changes made in this file will be lost!\n"); writeString( "*****************************************************************************/\n\n"); - } else if (m_format == Binary) { + break; + case Python3_Code: + case Python2_Code: + writeString("# Resource object code (Python "); + writeChar(m_format == Python3_Code ? '3' : '2'); + writeString(")\n"); + writeString("# Created by: object code\n"); + writeString("# Created by: The Resource Compiler for Qt version "); + writeByteArray(QT_VERSION_STR); + writeString("\n"); + writeString("# WARNING! All changes made in this file will be lost!\n\n"); + writeString("from PySide2 import QtCore\n\n"); + break; + case Binary: writeString("qres"); writeNumber4(0); writeNumber4(0); @@ -1055,6 +1113,9 @@ bool RCCResourceLibrary::writeHeader() writeNumber4(0); if (m_formatVersion >= 3) writeNumber4(m_overallFlags); + break; + default: + break; } return true; } @@ -1062,10 +1123,21 @@ bool RCCResourceLibrary::writeHeader() bool RCCResourceLibrary::writeDataBlobs() { Q_ASSERT(m_errorDevice); - if (m_format == C_Code) { + switch (m_format) { + case C_Code: writeString("static const unsigned char qt_resource_data[] = {\n"); - } else if (m_format == Binary) { + break; + case Python3_Code: + writeString("qt_resource_data = b\"\\\n"); + break; + case Python2_Code: + writeString("qt_resource_data = \"\\\n"); + break; + case Binary: m_dataOffset = m_out.size(); + break; + default: + break; } if (!m_root) @@ -1091,24 +1163,46 @@ bool RCCResourceLibrary::writeDataBlobs() } } } - if (m_format == C_Code) + switch (m_format) { + case C_Code: writeString("\n};\n\n"); - else if (m_format == Pass1) { + break; + case Python3_Code: + case Python2_Code: + writeString("\"\n\n"); + break; + case Pass1: if (offset < 8) offset = 8; writeString("\nstatic const unsigned char qt_resource_data["); writeByteArray(QByteArray::number(offset)); writeString("] = { 'Q', 'R', 'C', '_', 'D', 'A', 'T', 'A' };\n\n"); + break; + default: + break; } return true; } bool RCCResourceLibrary::writeDataNames() { - if (m_format == C_Code || m_format == Pass1) + switch (m_format) { + case C_Code: + case Pass1: writeString("static const unsigned char qt_resource_name[] = {\n"); - else if (m_format == Binary) + break; + case Python3_Code: + writeString("qt_resource_name = b\"\\\n"); + break; + case Python2_Code: + writeString("qt_resource_name = \"\\\n"); + break; + case Binary: m_namesOffset = m_out.size(); + break; + default: + break; + } QHash<QString, int> names; QStack<RCCFileInfo*> pending; @@ -1133,8 +1227,18 @@ bool RCCResourceLibrary::writeDataNames() } } } - if (m_format == C_Code || m_format == Pass1) + switch (m_format) { + case C_Code: + case Pass1: writeString("\n};\n\n"); + break; + case Python3_Code: + case Python2_Code: + writeString("\"\n\n"); + break; + default: + break; + } return true; } @@ -1149,10 +1253,24 @@ struct qt_rcc_compare_hash bool RCCResourceLibrary::writeDataStructure() { - if (m_format == C_Code || m_format == Pass1) + switch (m_format) { + case C_Code: + case Pass1: writeString("static const unsigned char qt_resource_struct[] = {\n"); - else if (m_format == Binary) + break; + case Python3_Code: + writeString("qt_resource_struct = b\"\\\n"); + break; + case Python2_Code: + writeString("qt_resource_struct = \"\\\n"); + break; + case Binary: m_treeOffset = m_out.size(); + break; + default: + break; + } + QStack<RCCFileInfo*> pending; if (!m_root) @@ -1196,8 +1314,18 @@ bool RCCResourceLibrary::writeDataStructure() pending.push(child); } } - if (m_format == C_Code || m_format == Pass1) + switch (m_format) { + case C_Code: + case Pass1: writeString("\n};\n\n"); + break; + case Python3_Code: + case Python2_Code: + writeString("\"\n\n"); + break; + default: + break; + } return true; } @@ -1387,6 +1515,16 @@ bool RCCResourceLibrary::writeInitializer() p[i++] = (m_overallFlags >> 8) & 0xff; p[i++] = (m_overallFlags >> 0) & 0xff; } + } else if (m_format == Python3_Code || m_format == Python2_Code) { + writeString("def qInitResources():\n"); + writeString(" QtCore.qRegisterResourceData(0x"); + write2HexDigits(m_formatVersion); + writeString(", qt_resource_struct, qt_resource_name, qt_resource_data)\n\n"); + writeString("def qCleanupResources():\n"); + writeString(" QtCore.qUnregisterResourceData(0x"); + write2HexDigits(m_formatVersion); + writeString(", qt_resource_struct, qt_resource_name, qt_resource_data)\n\n"); + writeString("qInitResources()\n"); } return true; } diff --git a/src/tools/rcc/rcc.h b/src/tools/rcc/rcc.h index ad1c5cd166..190c37a1f6 100644 --- a/src/tools/rcc/rcc.h +++ b/src/tools/rcc/rcc.h @@ -58,7 +58,7 @@ public: bool readFiles(bool listMode, QIODevice &errorDevice); - enum Format { Binary, C_Code, Pass1, Pass2 }; + enum Format { Binary, C_Code, Pass1, Pass2, Python3_Code, Python2_Code }; void setFormat(Format f) { m_format = f; } Format format() const { return m_format; } @@ -136,12 +136,14 @@ private: void writeAddNamespaceFunction(const QByteArray &name); void writeDecimal(int value); void writeHex(quint8 number); + void write2HexDigits(quint8 number); void writeNumber2(quint16 number); void writeNumber4(quint32 number); void writeNumber8(quint64 number); void writeChar(char c) { m_out.append(c); } void writeByteArray(const QByteArray &); void write(const char *, int len); + void writeString(const char *s) { write(s, static_cast<int>(strlen(s))); } #if QT_CONFIG(zstd) ZSTD_CCtx *m_zstdCCtx; diff --git a/src/tools/tracegen/etw.cpp b/src/tools/tracegen/etw.cpp index e839137915..acd81bd5c1 100644 --- a/src/tools/tracegen/etw.cpp +++ b/src/tools/tracegen/etw.cpp @@ -45,7 +45,6 @@ #include <qfile.h> #include <qfileinfo.h> #include <qtextstream.h> -#include <qregexp.h> #include <quuid.h> static inline QString providerVar(const QString &providerName) diff --git a/src/tools/tracegen/lttng.cpp b/src/tools/tracegen/lttng.cpp index f0fbca9e16..1aef1b3d17 100644 --- a/src/tools/tracegen/lttng.cpp +++ b/src/tools/tracegen/lttng.cpp @@ -46,7 +46,6 @@ #include <qfile.h> #include <qfileinfo.h> #include <qtextstream.h> -#include <qregexp.h> #include <qdebug.h> static void writeCtfMacro(QTextStream &stream, const Tracepoint::Field &field) 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..d16c859eed 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) << ");\n"; } 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,24 @@ 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) { m_refreshInitialization += m_indent; m_refreshInitialization += QLatin1String("Q_UNUSED("); m_refreshInitialization += varName ; m_refreshInitialization += QLatin1String(");\n"); } - m_output << m_option.indent << "void " << "retranslateUi(" << widgetClassName << " *" << varName << ")\n" - << m_option.indent << "{\n" + m_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 +579,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 +592,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 +607,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 +661,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 << 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 << ");\n"; } 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 +696,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 +785,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 +805,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 +817,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 +840,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 +856,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,7 +875,7 @@ 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()); @@ -883,8 +896,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,9 +966,12 @@ 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) @@ -1003,7 +1018,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,16 +1029,16 @@ 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"; } @@ -1036,7 +1051,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 << ");\n"; writeProperties(actionName, QLatin1String("QActionGroup"), node->elementProperty()); m_actionGroupChain.push(node); @@ -1050,13 +1066,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 +1085,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 +1127,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 +1159,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 +1200,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 +1216,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 +1251,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 +1291,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 +1323,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 +1337,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 +1363,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 +1400,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 +1500,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 +1519,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,7 +1533,7 @@ 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"; } @@ -1509,20 +1554,15 @@ 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"; @@ -1546,10 +1586,11 @@ 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) << ");\n"; } if (f->hasElementPointSize() && f->elementPointSize() > 0) { m_output << m_indent << fontName << ".setPointSize(" << f->elementPointSize() @@ -1558,39 +1599,51 @@ QString WriteInitialization::writeFontProperties(const DomFont *f) 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 +1651,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->elementSelectedOff()->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 +1745,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) << ";\n"; + 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,7 +1850,7 @@ 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"; } @@ -1794,8 +1867,9 @@ void WriteInitialization::writeColorGroup(DomColorGroup *colorGroup, const QStri << versionAdded.majorVersion() << ", " << versionAdded.minorVersion() << ", " << versionAdded.microVersion() << ")\n"; } - m_output << m_indent << paletteName << ".setBrush(" << group - << ", " << "QPalette::" << roleName + m_output << m_indent << paletteName << ".setBrush(" + << language::enumValue(group) << ", " + << "QPalette" << language::qualifier << roleName << ", " << brushName << ");\n"; if (!versionAdded.isNull()) m_output << "#endif\n"; @@ -1842,31 +1916,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 +1953,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 +1992,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 +2007,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 +2050,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,13 +2080,15 @@ 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_refreshOut << m_indent << varName << language::derefPointer + << "setItemText(" << i << ", " << trCall(text->elementString()) + << ')' << language::eol; } else { m_output << noTrCall(text->elementString()) << ");\n"; } @@ -2020,9 +2103,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 +2117,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 +2143,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 +2193,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 +2212,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 +2261,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 +2284,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 +2307,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 +2371,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 +2386,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 +2399,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 +2413,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 +2437,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 +2450,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 +2491,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 +2516,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 +2546,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(); + + const auto senderDecl = findDeclaration(senderName); + const auto receiverDecl = findDeclaration(receiverName); - if (sender.isEmpty() || receiver.isEmpty()) + 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; + } + + language::SignalSlot theSignal{senderDecl.name, connection->elementSignal(), + senderDecl.className}; + language::SignalSlot theSlot{receiverDecl.name, connection->elementSlot(), + receiverDecl.className}; - m_output << m_indent << "QObject::connect(" - << sender - << ", " - << "SIGNAL("<<connection->elementSignal()<<')' - << ", " - << receiver - << ", " - << "SLOT("<<connection->elementSlot()<<')' - << ");\n"; + m_output << m_indent; + language::formatConnection(m_output, theSignal, theSlot); + m_output << ";\n"; } static void generateMultiDirectiveBegin(QTextStream &outputStream, const QSet<QString> &directives) @@ -2470,14 +2594,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 +2609,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 +2636,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 +2648,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 +2666,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 +2685,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 +2704,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; |