From 2c96ee2ee4b57ef29a9c6b4c43e31aa1ded658d0 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Wed, 26 Jan 2022 11:09:51 +0100 Subject: [PATCH 01/12] Get rid of ConsoleProcess Use QtcProcess in Terminal mode instead. Change-Id: Iba237f3ee3e5802eed494e4ea9caf7c4ad1bc61a Reviewed-by: hjk Reviewed-by: --- src/libs/utils/CMakeLists.txt | 1 - src/libs/utils/consoleprocess.cpp | 866 ---------------------- src/libs/utils/consoleprocess.h | 108 --- src/libs/utils/utils.qbs | 2 - src/plugins/coreplugin/systemsettings.cpp | 1 - src/plugins/debugger/cdb/cdbengine.cpp | 1 - src/plugins/debugger/lldb/lldbengine.h | 1 - 7 files changed, 980 deletions(-) delete mode 100644 src/libs/utils/consoleprocess.cpp delete mode 100644 src/libs/utils/consoleprocess.h diff --git a/src/libs/utils/CMakeLists.txt b/src/libs/utils/CMakeLists.txt index f55dc761078..780f3e2017a 100644 --- a/src/libs/utils/CMakeLists.txt +++ b/src/libs/utils/CMakeLists.txt @@ -25,7 +25,6 @@ add_qtc_library(Utils commandline.cpp commandline.h completinglineedit.cpp completinglineedit.h completingtextedit.cpp completingtextedit.h - consoleprocess.cpp consoleprocess.h cpplanguage_details.h crumblepath.cpp crumblepath.h declarationmacros.h diff --git a/src/libs/utils/consoleprocess.cpp b/src/libs/utils/consoleprocess.cpp deleted file mode 100644 index 724ba617b27..00000000000 --- a/src/libs/utils/consoleprocess.cpp +++ /dev/null @@ -1,866 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** 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. -** -****************************************************************************/ - -#include "consoleprocess.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef Q_OS_WIN - -# include -# include -# include - -#else - -# include -# include -# include -# include -# include - -#endif - -namespace Utils { - -static QString modeOption(ConsoleProcess::Mode m) -{ - switch (m) { - case ConsoleProcess::Debug: - return QLatin1String("debug"); - case ConsoleProcess::Suspend: - return QLatin1String("suspend"); - case ConsoleProcess::Run: - break; - } - return QLatin1String("run"); -} - -static QString msgCommChannelFailed(const QString &error) -{ - return ConsoleProcess::tr("Cannot set up communication channel: %1").arg(error); -} - -static QString msgPromptToClose() -{ - // Shown in a terminal which might have a different character set on Windows. - return ConsoleProcess::tr("Press to close this window..."); -} - -static QString msgCannotCreateTempFile(const QString &why) -{ - return ConsoleProcess::tr("Cannot create temporary file: %1").arg(why); -} - -static QString msgCannotWriteTempFile() -{ - return ConsoleProcess::tr("Cannot write temporary file. Disk full?"); -} - -static QString msgCannotCreateTempDir(const QString & dir, const QString &why) -{ - return ConsoleProcess::tr("Cannot create temporary directory \"%1\": %2").arg(dir, why); -} - -static QString msgUnexpectedOutput(const QByteArray &what) -{ - return ConsoleProcess::tr("Unexpected output from helper program (%1).").arg(QString::fromLatin1(what)); -} - -static QString msgCannotChangeToWorkDir(const FilePath &dir, const QString &why) -{ - return ConsoleProcess::tr("Cannot change to working directory \"%1\": %2").arg(dir.toString(), why); -} - -static QString msgCannotExecute(const QString & p, const QString &why) -{ - return ConsoleProcess::tr("Cannot execute \"%1\": %2").arg(p, why); -} - -// ConsoleProcessPrivate - -class ConsoleProcessPrivate -{ -public: - ConsoleProcessPrivate() = default; - - ConsoleProcess::Mode m_mode = ConsoleProcess::Run; - FilePath m_workingDir; - Environment m_environment; - qint64 m_processId = 0; - int m_exitCode = 0; - CommandLine m_commandLine; - QProcess::ExitStatus m_appStatus = QProcess::NormalExit; - QLocalServer m_stubServer; - QLocalSocket *m_stubSocket = nullptr; - QTemporaryFile *m_tempFile = nullptr; - QProcess::ProcessError m_error = QProcess::UnknownError; - QString m_errorString; - bool m_abortOnMetaChars = true; - bool m_runAsRoot = false; - - // Used on Unix only - QtcProcess m_process; - QTimer *m_stubConnectTimer = nullptr; - QByteArray m_stubServerDir; - - // Used on Windows only - qint64 m_appMainThreadId = 0; - -#ifdef Q_OS_WIN - PROCESS_INFORMATION *m_pid = nullptr; - HANDLE m_hInferior = NULL; - QWinEventNotifier *inferiorFinishedNotifier = nullptr; - QWinEventNotifier *processFinishedNotifier = nullptr; -#endif -}; - - -// ConsoleProcess - -ConsoleProcess::ConsoleProcess(QObject *parent) : - QObject(parent), d(new ConsoleProcessPrivate) -{ - connect(&d->m_stubServer, &QLocalServer::newConnection, - this, &ConsoleProcess::stubConnectionAvailable); - - d->m_process.setProcessChannelMode(QProcess::ForwardedChannels); -} - -ConsoleProcess::~ConsoleProcess() -{ - stopProcess(); - delete d; -} - -void ConsoleProcess::setCommand(const CommandLine &command) -{ - d->m_commandLine = command; -} - -const CommandLine &ConsoleProcess::commandLine() const -{ - return d->m_commandLine; -} - -static QString quoteWinCommand(const QString &program) -{ - const QChar doubleQuote = QLatin1Char('"'); - - // add the program as the first arg ... it works better - QString programName = program; - programName.replace(QLatin1Char('/'), QLatin1Char('\\')); - if (!programName.startsWith(doubleQuote) && !programName.endsWith(doubleQuote) - && programName.contains(QLatin1Char(' '))) { - programName.prepend(doubleQuote); - programName.append(doubleQuote); - } - return programName; -} - -static QString quoteWinArgument(const QString &arg) -{ - if (arg.isEmpty()) - return QString::fromLatin1("\"\""); - - QString ret(arg); - // Quotes are escaped and their preceding backslashes are doubled. - ret.replace(QRegularExpression("(\\\\*)\""), "\\1\\1\\\""); - if (ret.contains(QRegularExpression("\\s"))) { - // 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; -} - -// Quote a Windows command line correctly for the "CreateProcess" API -static QString createWinCommandline(const QString &program, const QStringList &args) -{ - QString programName = quoteWinCommand(program); - for (const QString &arg : args) { - programName += QLatin1Char(' '); - programName += quoteWinArgument(arg); - } - return programName; -} - -static QString createWinCommandline(const QString &program, const QString &args) -{ - QString programName = quoteWinCommand(program); - if (!args.isEmpty()) { - programName += QLatin1Char(' '); - programName += args; - } - return programName; -} - -bool ConsoleProcess::startTerminalEmulator(const QString &workingDir, const Environment &env) -{ -#ifdef Q_OS_WIN - STARTUPINFO si; - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - - PROCESS_INFORMATION pinfo; - ZeroMemory(&pinfo, sizeof(pinfo)); - - QString cmdLine = createWinCommandline( - QString::fromLocal8Bit(qgetenv("COMSPEC")), QString()); - // cmdLine is assumed to be detached - - // https://blogs.msdn.microsoft.com/oldnewthing/20090601-00/?p=18083 - - QString totalEnvironment = env.toStringList().join(QChar(QChar::Null)) + QChar(QChar::Null); - LPVOID envPtr = (env != Environment::systemEnvironment()) - ? (WCHAR *)(totalEnvironment.utf16()) : nullptr; - - bool success = CreateProcessW(0, (WCHAR *)cmdLine.utf16(), - 0, 0, FALSE, CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT, - envPtr, workingDir.isEmpty() ? 0 : (WCHAR *)workingDir.utf16(), - &si, &pinfo); - - if (success) { - CloseHandle(pinfo.hThread); - CloseHandle(pinfo.hProcess); - } - - return success; -#else - const TerminalCommand term = TerminalCommand::terminalEmulator(); - QProcess process; - process.setProgram(term.command); - process.setArguments(ProcessArgs::splitArgs(term.openArgs)); - process.setProcessEnvironment(env.toProcessEnvironment()); - process.setWorkingDirectory(workingDir); - - return process.startDetached(); -#endif -} - -void ConsoleProcess::setAbortOnMetaChars(bool abort) -{ - d->m_abortOnMetaChars = abort; -} - -qint64 ConsoleProcess::applicationMainThreadID() const -{ - if (HostOsInfo::isWindowsHost()) - return d->m_appMainThreadId; - return -1; -} - -void ConsoleProcess::start() -{ - if (isRunning()) - return; - - d->m_errorString.clear(); - d->m_error = QProcess::UnknownError; - -#ifdef Q_OS_WIN - - QString pcmd; - QString pargs; - if (d->m_mode != Run) { // The debugger engines already pre-process the arguments. - pcmd = d->m_commandLine.executable().toString(); - pargs = d->m_commandLine.arguments(); - } else { - ProcessArgs outArgs; - ProcessArgs::prepareCommand(d->m_commandLine, &pcmd, &outArgs, - &d->m_environment, &d->m_workingDir); - pargs = outArgs.toWindowsArgs(); - } - - const QString err = stubServerListen(); - if (!err.isEmpty()) { - emitError(QProcess::FailedToStart, msgCommChannelFailed(err)); - return; - } - - QStringList env = d->m_environment.toStringList(); - if (!env.isEmpty()) { - d->m_tempFile = new QTemporaryFile(); - if (!d->m_tempFile->open()) { - cleanupAfterStartFailure(msgCannotCreateTempFile(d->m_tempFile->errorString())); - return; - } - QString outString; - QTextStream out(&outString); - // Add PATH and SystemRoot environment variables in case they are missing - const QStringList fixedEnvironment = [env] { - QStringList envStrings = env; - // add PATH if necessary (for DLL loading) - if (envStrings.filter(QRegularExpression("^PATH=.*", QRegularExpression::CaseInsensitiveOption)).isEmpty()) { - QByteArray path = qgetenv("PATH"); - if (!path.isEmpty()) - envStrings.prepend(QString::fromLatin1("PATH=%1").arg(QString::fromLocal8Bit(path))); - } - // add systemroot if needed - if (envStrings.filter(QRegularExpression("^SystemRoot=.*", QRegularExpression::CaseInsensitiveOption)).isEmpty()) { - QByteArray systemRoot = qgetenv("SystemRoot"); - if (!systemRoot.isEmpty()) - envStrings.prepend(QString::fromLatin1("SystemRoot=%1").arg(QString::fromLocal8Bit(systemRoot))); - } - return envStrings; - }(); - - for (const QString &var : fixedEnvironment) - out << var << QChar(0); - out << QChar(0); - const QTextCodec *textCodec = QTextCodec::codecForName("UTF-16LE"); - QTC_CHECK(textCodec); - const QByteArray outBytes = textCodec ? textCodec->fromUnicode(outString) : QByteArray(); - if (!textCodec || d->m_tempFile->write(outBytes) < 0) { - cleanupAfterStartFailure(msgCannotWriteTempFile()); - return; - } - d->m_tempFile->flush(); - } - - STARTUPINFO si; - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - - d->m_pid = new PROCESS_INFORMATION; - ZeroMemory(d->m_pid, sizeof(PROCESS_INFORMATION)); - - QString workDir = workingDirectory().toUserOutput(); - if (!workDir.isEmpty() && !workDir.endsWith(QLatin1Char('\\'))) - workDir.append(QLatin1Char('\\')); - - QStringList stubArgs; - stubArgs << modeOption(d->m_mode) - << d->m_stubServer.fullServerName() - << workDir - << (d->m_tempFile ? d->m_tempFile->fileName() : QString()) - << createWinCommandline(pcmd, pargs) - << msgPromptToClose(); - - const QString cmdLine = createWinCommandline( - QCoreApplication::applicationDirPath() + QLatin1String("/qtcreator_process_stub.exe"), stubArgs); - - bool success = CreateProcessW(0, (WCHAR*)cmdLine.utf16(), - 0, 0, FALSE, CREATE_NEW_CONSOLE, - 0, 0, - &si, d->m_pid); - - if (!success) { - delete d->m_pid; - d->m_pid = nullptr; - const QString msg = tr("The process \"%1\" could not be started: %2") - .arg(cmdLine, winErrorMessage(GetLastError())); - cleanupAfterStartFailure(msg); - return; - } - - d->processFinishedNotifier = new QWinEventNotifier(d->m_pid->hProcess, this); - connect(d->processFinishedNotifier, &QWinEventNotifier::activated, - this, &ConsoleProcess::stubExited); - -#else - - ProcessArgs::SplitError perr; - ProcessArgs pargs = ProcessArgs::prepareArgs(d->m_commandLine.arguments(), - &perr, - HostOsInfo::hostOs(), - &d->m_environment, - &d->m_workingDir, - d->m_abortOnMetaChars); - - QString pcmd; - if (perr == ProcessArgs::SplitOk) { - pcmd = d->m_commandLine.executable().toString(); - } else { - if (perr != ProcessArgs::FoundMeta) { - emitError(QProcess::FailedToStart, tr("Quoting error in command.")); - return; - } - if (d->m_mode == Debug) { - // FIXME: QTCREATORBUG-2809 - emitError(QProcess::FailedToStart, tr("Debugging complex shell commands in a terminal" - " is currently not supported.")); - return; - } - pcmd = qEnvironmentVariable("SHELL", "/bin/sh"); - pargs = ProcessArgs::createUnixArgs( - {"-c", (ProcessArgs::quoteArg(d->m_commandLine.executable().toString()) - + ' ' + d->m_commandLine.arguments())}); - } - - ProcessArgs::SplitError qerr; - const TerminalCommand terminal = TerminalCommand::terminalEmulator(); - const ProcessArgs terminalArgs = ProcessArgs::prepareArgs(terminal.executeArgs, - &qerr, - HostOsInfo::hostOs(), - &d->m_environment, - &d->m_workingDir); - if (qerr != ProcessArgs::SplitOk) { - emitError(QProcess::FailedToStart, qerr == ProcessArgs::BadQuoting - ? tr("Quoting error in terminal command.") - : tr("Terminal command may not be a shell command.")); - return; - } - - const QString err = stubServerListen(); - if (!err.isEmpty()) { - emitError(QProcess::FailedToStart, msgCommChannelFailed(err)); - return; - } - - d->m_environment.unset(QLatin1String("TERM")); - - const QStringList env = d->m_environment.toStringList(); - if (!env.isEmpty()) { - d->m_tempFile = new QTemporaryFile(); - if (!d->m_tempFile->open()) { - cleanupAfterStartFailure(msgCannotCreateTempFile(d->m_tempFile->errorString())); - return; - } - QByteArray contents; - for (const QString &var : env) { - const QByteArray l8b = var.toLocal8Bit(); - contents.append(l8b.constData(), l8b.size() + 1); - } - if (d->m_tempFile->write(contents) != contents.size() || !d->m_tempFile->flush()) { - cleanupAfterStartFailure(msgCannotWriteTempFile()); - return; - } - } - - const QString stubPath = QCoreApplication::applicationDirPath() - + QLatin1String("/" RELATIVE_LIBEXEC_PATH "/qtcreator_process_stub"); - - QStringList allArgs = terminalArgs.toUnixArgs(); - if (d->m_runAsRoot) - allArgs << "sudo" << "-A"; - - allArgs << stubPath - << modeOption(d->m_mode) - << d->m_stubServer.fullServerName() - << msgPromptToClose() - << workingDirectory().path() - << (d->m_tempFile ? d->m_tempFile->fileName() : QString()) - << QString::number(getpid()) - << pcmd - << pargs.toUnixArgs(); - - if (terminal.needsQuotes) - allArgs = QStringList { ProcessArgs::joinArgs(allArgs) }; - - d->m_process.setEnvironment(d->m_environment); - d->m_process.setCommand({FilePath::fromString(terminal.command), allArgs}); - d->m_process.start(); - if (!d->m_process.waitForStarted()) { - const QString msg = tr("Cannot start the terminal emulator \"%1\", change the setting in the " - "Environment options.").arg(terminal.command); - cleanupAfterStartFailure(msg); - return; - } - d->m_stubConnectTimer = new QTimer(this); - connect(d->m_stubConnectTimer, &QTimer::timeout, this, &ConsoleProcess::stopProcess); - d->m_stubConnectTimer->setSingleShot(true); - d->m_stubConnectTimer->start(10000); - -#endif -} - -void ConsoleProcess::cleanupAfterStartFailure(const QString &errorMessage) -{ - stubServerShutdown(); - emitError(QProcess::FailedToStart, errorMessage); - delete d->m_tempFile; - d->m_tempFile = nullptr; -} - -void ConsoleProcess::finish(int exitCode, QProcess::ExitStatus exitStatus) -{ - d->m_processId = 0; - d->m_exitCode = exitCode; - d->m_appStatus = exitStatus; - emit finished(); -} - -void Utils::ConsoleProcess::kickoffProcess() -{ -#ifdef Q_OS_WIN - // Not used. -#else - if (d->m_stubSocket && d->m_stubSocket->isWritable()) { - d->m_stubSocket->write("c", 1); - d->m_stubSocket->flush(); - } -#endif -} - -void ConsoleProcess::interruptProcess() -{ -#ifdef Q_OS_WIN - // Not used. -#else - if (d->m_stubSocket && d->m_stubSocket->isWritable()) { - d->m_stubSocket->write("i", 1); - d->m_stubSocket->flush(); - } -#endif -} - -void ConsoleProcess::killProcess() -{ -#ifdef Q_OS_WIN - if (d->m_hInferior != NULL) { - TerminateProcess(d->m_hInferior, (unsigned)-1); - cleanupInferior(); - } -#else - if (d->m_stubSocket && d->m_stubSocket->isWritable()) { - d->m_stubSocket->write("k", 1); - d->m_stubSocket->flush(); - } -#endif - d->m_processId = 0; -} - -void ConsoleProcess::killStub() -{ -#ifdef Q_OS_WIN - if (d->m_pid) { - TerminateProcess(d->m_pid->hProcess, (unsigned)-1); - WaitForSingleObject(d->m_pid->hProcess, INFINITE); - cleanupStub(); - } -#else - if (d->m_stubSocket && d->m_stubSocket->isWritable()) { - d->m_stubSocket->write("s", 1); - d->m_stubSocket->flush(); - } - stubServerShutdown(); -#endif -} - -void ConsoleProcess::stopProcess() -{ - killProcess(); - killStub(); - if (isRunning() && HostOsInfo::isAnyUnixHost()) { - d->m_process.terminate(); - if (!d->m_process.waitForFinished(1000) && d->m_process.state() == QProcess::Running) { - d->m_process.kill(); - d->m_process.waitForFinished(); - } - } -} - -bool ConsoleProcess::isRunning() const -{ -#ifdef Q_OS_WIN - return d->m_pid != nullptr; -#else - return d->m_process.state() != QProcess::NotRunning - || (d->m_stubSocket && d->m_stubSocket->isOpen()); -#endif -} - -QString ConsoleProcess::stubServerListen() -{ -#ifdef Q_OS_WIN - if (d->m_stubServer.listen(QString::fromLatin1("creator-%1-%2") - .arg(QCoreApplication::applicationPid()) - .arg(rand()))) - return QString(); - return d->m_stubServer.errorString(); -#else - // We need to put the socket in a private directory, as some systems simply do not - // check the file permissions of sockets. - QString stubFifoDir; - while (true) { - { - QTemporaryFile tf; - if (!tf.open()) - return msgCannotCreateTempFile(tf.errorString()); - stubFifoDir = tf.fileName(); - } - // By now the temp file was deleted again - d->m_stubServerDir = QFile::encodeName(stubFifoDir); - if (!::mkdir(d->m_stubServerDir.constData(), 0700)) - break; - if (errno != EEXIST) - return msgCannotCreateTempDir(stubFifoDir, QString::fromLocal8Bit(strerror(errno))); - } - const QString stubServer = stubFifoDir + QLatin1String("/stub-socket"); - if (!d->m_stubServer.listen(stubServer)) { - ::rmdir(d->m_stubServerDir.constData()); - return tr("Cannot create socket \"%1\": %2").arg(stubServer, d->m_stubServer.errorString()); - } - return QString(); -#endif -} - -void ConsoleProcess::stubServerShutdown() -{ -#ifdef Q_OS_WIN - delete d->m_stubSocket; - d->m_stubSocket = nullptr; - if (d->m_stubServer.isListening()) - d->m_stubServer.close(); -#else - if (d->m_stubSocket) { - readStubOutput(); // we could get the shutdown signal before emptying the buffer - d->m_stubSocket->disconnect(); // avoid getting queued readyRead signals - d->m_stubSocket->deleteLater(); // we might be called from the disconnected signal of m_stubSocket - } - d->m_stubSocket = nullptr; - if (d->m_stubServer.isListening()) { - d->m_stubServer.close(); - ::rmdir(d->m_stubServerDir.constData()); - } -#endif -} - -void ConsoleProcess::stubConnectionAvailable() -{ - if (d->m_stubConnectTimer) { - delete d->m_stubConnectTimer; - d->m_stubConnectTimer = nullptr; - } - - d->m_stubSocket = d->m_stubServer.nextPendingConnection(); - connect(d->m_stubSocket, &QIODevice::readyRead, this, &ConsoleProcess::readStubOutput); - - if (HostOsInfo::isAnyUnixHost()) - connect(d->m_stubSocket, &QLocalSocket::disconnected, this, &ConsoleProcess::stubExited); -} - -static QString errorMsg(int code) -{ - return QString::fromLocal8Bit(strerror(code)); -} - -void ConsoleProcess::readStubOutput() -{ - while (d->m_stubSocket->canReadLine()) { - QByteArray out = d->m_stubSocket->readLine(); -#ifdef Q_OS_WIN - out.chop(2); // \r\n - if (out.startsWith("err:chdir ")) { - emitError(QProcess::FailedToStart, msgCannotChangeToWorkDir(workingDirectory(), winErrorMessage(out.mid(10).toInt()))); - } else if (out.startsWith("err:exec ")) { - emitError(QProcess::FailedToStart, msgCannotExecute(d->m_commandLine.executable().toUserOutput(), winErrorMessage(out.mid(9).toInt()))); - } else if (out.startsWith("thread ")) { // Windows only - d->m_appMainThreadId = out.mid(7).toLongLong(); - } else if (out.startsWith("pid ")) { - // Will not need it any more - delete d->m_tempFile; - d->m_tempFile = nullptr; - d->m_processId = out.mid(4).toLongLong(); - - d->m_hInferior = OpenProcess( - SYNCHRONIZE | PROCESS_QUERY_INFORMATION | PROCESS_TERMINATE, - FALSE, d->m_processId); - if (d->m_hInferior == NULL) { - emitError(QProcess::FailedToStart, tr("Cannot obtain a handle to the inferior: %1") - .arg(winErrorMessage(GetLastError()))); - // Uhm, and now what? - continue; - } - d->inferiorFinishedNotifier = new QWinEventNotifier(d->m_hInferior, this); - connect(d->inferiorFinishedNotifier, &QWinEventNotifier::activated, this, [this] { - DWORD chldStatus; - - if (!GetExitCodeProcess(d->m_hInferior, &chldStatus)) - emitError(QProcess::UnknownError, tr("Cannot obtain exit status from inferior: %1") - .arg(winErrorMessage(GetLastError()))); - cleanupInferior(); - finish(chldStatus, QProcess::NormalExit); - }); - - emit started(); - } else { - emitError(QProcess::UnknownError, msgUnexpectedOutput(out)); - TerminateProcess(d->m_pid->hProcess, (unsigned)-1); - break; - } -#else - out.chop(1); // \n - if (out.startsWith("err:chdir ")) { - emitError(QProcess::FailedToStart, msgCannotChangeToWorkDir(workingDirectory(), errorMsg(out.mid(10).toInt()))); - } else if (out.startsWith("err:exec ")) { - emitError(QProcess::FailedToStart, msgCannotExecute(d->m_commandLine.executable().toString(), errorMsg(out.mid(9).toInt()))); - } else if (out.startsWith("spid ")) { - delete d->m_tempFile; - d->m_tempFile = nullptr; - } else if (out.startsWith("pid ")) { - d->m_processId = out.mid(4).toInt(); - emit started(); - } else if (out.startsWith("exit ")) { - finish(out.mid(5).toInt(), QProcess::NormalExit); - } else if (out.startsWith("crash ")) { - finish(out.mid(6).toInt(), QProcess::CrashExit); - } else { - emitError(QProcess::UnknownError, msgUnexpectedOutput(out)); - d->m_process.terminate(); - break; - } -#endif - } // while -} - -void ConsoleProcess::stubExited() -{ - // The stub exit might get noticed before we read the pid for the kill on Windows - // or the error status elsewhere. - if (d->m_stubSocket && d->m_stubSocket->state() == QLocalSocket::ConnectedState) - d->m_stubSocket->waitForDisconnected(); - -#ifdef Q_OS_WIN - cleanupStub(); - if (d->m_hInferior != NULL) { - TerminateProcess(d->m_hInferior, (unsigned)-1); - cleanupInferior(); - finish(-1, QProcess::CrashExit); - } -#else - stubServerShutdown(); - delete d->m_tempFile; - d->m_tempFile = nullptr; - if (d->m_processId) - finish(-1, QProcess::CrashExit); -#endif -} - -void ConsoleProcess::cleanupInferior() -{ -#ifdef Q_OS_WIN - delete d->inferiorFinishedNotifier; - d->inferiorFinishedNotifier = nullptr; - CloseHandle(d->m_hInferior); - d->m_hInferior = NULL; -#endif -} - -void ConsoleProcess::cleanupStub() -{ -#ifdef Q_OS_WIN - stubServerShutdown(); - delete d->processFinishedNotifier; - d->processFinishedNotifier = nullptr; - CloseHandle(d->m_pid->hThread); - CloseHandle(d->m_pid->hProcess); - delete d->m_pid; - d->m_pid = nullptr; - delete d->m_tempFile; - d->m_tempFile = nullptr; -#endif -} - -void ConsoleProcess::setMode(Mode m) -{ - d->m_mode = m; -} - -ConsoleProcess::Mode ConsoleProcess::mode() const -{ - return d->m_mode; -} - -qint64 ConsoleProcess::processId() const -{ - return d->m_processId; -} - -int ConsoleProcess::exitCode() const -{ - return d->m_exitCode; -} // This will be the signal number if exitStatus == CrashExit - -QProcess::ExitStatus ConsoleProcess::exitStatus() const -{ - return d->m_appStatus; -} - -void ConsoleProcess::setWorkingDirectory(const FilePath &dir) -{ - d->m_workingDir = dir; -} - -FilePath ConsoleProcess::workingDirectory() const -{ - return d->m_workingDir; -} - -void ConsoleProcess::setEnvironment(const Environment &env) -{ - d->m_environment = env; -} - -const Utils::Environment &ConsoleProcess::environment() const -{ - return d->m_environment; -} - -void Utils::ConsoleProcess::setRunAsRoot(bool on) -{ - d->m_runAsRoot = on; -} - -QProcess::ProcessError ConsoleProcess::error() const -{ - return d->m_error; -} - -QString ConsoleProcess::errorString() const -{ - return d->m_errorString; -} - -void ConsoleProcess::emitError(QProcess::ProcessError err, const QString &errorString) -{ - d->m_error = err; - d->m_errorString = errorString; - emit errorOccurred(err); -} - -} // Utils diff --git a/src/libs/utils/consoleprocess.h b/src/libs/utils/consoleprocess.h deleted file mode 100644 index f37e5d4528b..00000000000 --- a/src/libs/utils/consoleprocess.h +++ /dev/null @@ -1,108 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** 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. -** -****************************************************************************/ - -#pragma once - -#include "utils_global.h" - -#include - -namespace Utils { - -class CommandLine; -class Environment; -class FilePath; - -class QTCREATOR_UTILS_EXPORT ConsoleProcess : public QObject -{ - Q_OBJECT - -public: - enum Mode { Run, Debug, Suspend }; - - explicit ConsoleProcess(QObject *parent = nullptr); - ~ConsoleProcess() override; - - void setCommand(const Utils::CommandLine &command); - const Utils::CommandLine &commandLine() const; - - void setAbortOnMetaChars(bool abort); - - void setWorkingDirectory(const Utils::FilePath &dir); - Utils::FilePath workingDirectory() const; - - void setEnvironment(const Environment &env); - const Environment &environment() const; - - void setRunAsRoot(bool on); - - QProcess::ProcessError error() const; - QString errorString() const; - - void start(); - void stopProcess(); - -public: - void setMode(Mode m); - Mode mode() const; - - bool isRunning() const; // This reflects the state of the console+stub - qint64 processId() const; - - void kickoffProcess(); - void interruptProcess(); - - qint64 applicationMainThreadID() const; - - int exitCode() const; - QProcess::ExitStatus exitStatus() const; - - static bool startTerminalEmulator(const QString &workingDir, const Utils::Environment &env); - -signals: - void errorOccurred(QProcess::ProcessError error); - - // These reflect the state of the actual client process - void started(); - void finished(); - -private: - void stubConnectionAvailable(); - void readStubOutput(); - void stubExited(); - void cleanupAfterStartFailure(const QString &errorMessage); - void finish(int exitCode, QProcess::ExitStatus exitStatus); - void killProcess(); - void killStub(); - void emitError(QProcess::ProcessError err, const QString &errorString); - QString stubServerListen(); - void stubServerShutdown(); - void cleanupStub(); - void cleanupInferior(); - - class ConsoleProcessPrivate *d; -}; - -} // Utils diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs index 1f38d704267..e6ad32fb028 100644 --- a/src/libs/utils/utils.qbs +++ b/src/libs/utils/utils.qbs @@ -68,8 +68,6 @@ Project { "completinglineedit.h", "completingtextedit.cpp", "completingtextedit.h", - "consoleprocess.cpp", - "consoleprocess.h", "cpplanguage_details.h", "crumblepath.cpp", "crumblepath.h", diff --git a/src/plugins/coreplugin/systemsettings.cpp b/src/plugins/coreplugin/systemsettings.cpp index 77809595590..a22afd61ba1 100644 --- a/src/plugins/coreplugin/systemsettings.cpp +++ b/src/plugins/coreplugin/systemsettings.cpp @@ -39,7 +39,6 @@ #include #include -#include #include #include #include diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index c44a0c6df9a..520a2cb44f1 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -62,7 +62,6 @@ #include #include -#include #include #include #include diff --git a/src/plugins/debugger/lldb/lldbengine.h b/src/plugins/debugger/lldb/lldbengine.h index 70ddf2aad04..4d80c0b9fd6 100644 --- a/src/plugins/debugger/lldb/lldbengine.h +++ b/src/plugins/debugger/lldb/lldbengine.h @@ -33,7 +33,6 @@ #include #include -#include #include #include From 5207374d5d230d6307fa3a839212c24ae627c635 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 13 Dec 2021 12:06:11 +0100 Subject: [PATCH 02/12] ProjectExplorer: Allow multi-selection in issues pane Users should be able to copy or remove several issues at once. Fixes: QTCREATORBUG-25547 Fixes: QTCREATORBUG-26720 Change-Id: I1ac75a3445c37200b6a01dd8c5d79d2b69c54a3c Reviewed-by: Christian Stenger --- .../projectexplorer/copytaskhandler.cpp | 38 +++++----- src/plugins/projectexplorer/copytaskhandler.h | 5 +- src/plugins/projectexplorer/itaskhandler.h | 14 +++- .../projectexplorer/removetaskhandler.cpp | 5 +- .../projectexplorer/removetaskhandler.h | 5 +- src/plugins/projectexplorer/taskmodel.cpp | 14 ++++ src/plugins/projectexplorer/taskmodel.h | 2 + src/plugins/projectexplorer/taskwindow.cpp | 75 +++++++++++-------- src/plugins/projectexplorer/taskwindow.h | 1 - 9 files changed, 99 insertions(+), 60 deletions(-) diff --git a/src/plugins/projectexplorer/copytaskhandler.cpp b/src/plugins/projectexplorer/copytaskhandler.cpp index 6a12c5251dd..4f9257cb01d 100644 --- a/src/plugins/projectexplorer/copytaskhandler.cpp +++ b/src/plugins/projectexplorer/copytaskhandler.cpp @@ -25,8 +25,6 @@ #include "copytaskhandler.h" -#include "task.h" - #include #include @@ -36,25 +34,27 @@ using namespace ProjectExplorer; using namespace ProjectExplorer::Internal; -void CopyTaskHandler::handle(const Task &task) +void CopyTaskHandler::handle(const Tasks &tasks) { - QString type; - switch (task.type) { - case Task::Error: - //: Task is of type: error - type = tr("error:") + QLatin1Char(' '); - break; - case Task::Warning: - //: Task is of type: warning - type = tr("warning:") + QLatin1Char(' '); - break; - default: - break; + QStringList lines; + for (const Task &task : tasks) { + QString type; + switch (task.type) { + case Task::Error: + //: Task is of type: error + type = tr("error:") + QLatin1Char(' '); + break; + case Task::Warning: + //: Task is of type: warning + type = tr("warning:") + QLatin1Char(' '); + break; + default: + break; + } + lines << task.file.toUserOutput() + ':' + QString::number(task.line) + + ": " + type + task.description(); } - - QApplication::clipboard()->setText(task.file.toUserOutput() + QLatin1Char(':') + - QString::number(task.line) + QLatin1String(": ") - + type + task.description()); + QApplication::clipboard()->setText(lines.join('\n')); } Utils::Id CopyTaskHandler::actionManagerId() const diff --git a/src/plugins/projectexplorer/copytaskhandler.h b/src/plugins/projectexplorer/copytaskhandler.h index da95a413c4b..8c4b4dc1da2 100644 --- a/src/plugins/projectexplorer/copytaskhandler.h +++ b/src/plugins/projectexplorer/copytaskhandler.h @@ -35,8 +35,9 @@ class CopyTaskHandler : public ITaskHandler Q_OBJECT public: - bool canHandle(const Task &) const override { return true; } - void handle(const Task &task) override; + CopyTaskHandler() : ITaskHandler(true) {} + + void handle(const Tasks &tasks) override; Utils::Id actionManagerId() const override; QAction *createAction(QObject *parent) const override; }; diff --git a/src/plugins/projectexplorer/itaskhandler.h b/src/plugins/projectexplorer/itaskhandler.h index 199e243988c..20a85ed5751 100644 --- a/src/plugins/projectexplorer/itaskhandler.h +++ b/src/plugins/projectexplorer/itaskhandler.h @@ -26,6 +26,7 @@ #pragma once #include "projectexplorer_export.h" +#include "task.h" #include @@ -37,21 +38,26 @@ class QAction; QT_END_NAMESPACE namespace ProjectExplorer { -class Task; class PROJECTEXPLORER_EXPORT ITaskHandler : public QObject { Q_OBJECT public: - ITaskHandler(); + explicit ITaskHandler(bool isMultiHandler = false); ~ITaskHandler() override; virtual bool isDefaultHandler() const { return false; } - virtual bool canHandle(const Task &) const = 0; - virtual void handle(const Task &) = 0; + virtual bool canHandle(const Task &) const { return m_isMultiHandler; } + virtual void handle(const Task &); // Non-multi-handlers should implement this. + virtual void handle(const Tasks &tasks); // Multi-handlers should implement this. virtual Utils::Id actionManagerId() const { return Utils::Id(); } virtual QAction *createAction(QObject *parent) const = 0; + + bool canHandle(const Tasks &tasks) const; + +private: + const bool m_isMultiHandler; }; } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/removetaskhandler.cpp b/src/plugins/projectexplorer/removetaskhandler.cpp index b8abc22e11d..7c8813b79f7 100644 --- a/src/plugins/projectexplorer/removetaskhandler.cpp +++ b/src/plugins/projectexplorer/removetaskhandler.cpp @@ -33,9 +33,10 @@ namespace ProjectExplorer { namespace Internal { -void RemoveTaskHandler::handle(const Task &task) +void RemoveTaskHandler::handle(const Tasks &tasks) { - TaskHub::removeTask(task); + for (const Task &task : tasks) + TaskHub::removeTask(task); } QAction *RemoveTaskHandler::createAction(QObject *parent) const diff --git a/src/plugins/projectexplorer/removetaskhandler.h b/src/plugins/projectexplorer/removetaskhandler.h index ae320d029de..ff624bc5073 100644 --- a/src/plugins/projectexplorer/removetaskhandler.h +++ b/src/plugins/projectexplorer/removetaskhandler.h @@ -35,8 +35,9 @@ class RemoveTaskHandler : public ITaskHandler Q_OBJECT public: - bool canHandle(const Task &) const override { return true; } - void handle(const Task &task) override; + RemoveTaskHandler() : ITaskHandler(true) {} + + void handle(const Tasks &tasks) override; QAction *createAction(QObject *parent) const override; }; diff --git a/src/plugins/projectexplorer/taskmodel.cpp b/src/plugins/projectexplorer/taskmodel.cpp index b9b74bb340c..36b6c942a1f 100644 --- a/src/plugins/projectexplorer/taskmodel.cpp +++ b/src/plugins/projectexplorer/taskmodel.cpp @@ -29,6 +29,7 @@ #include "task.h" #include "taskhub.h" +#include #include #include @@ -286,6 +287,13 @@ Task TaskModel::task(const QModelIndex &index) const return m_tasks.at(row); } +Tasks TaskModel::tasks(const QModelIndexList &indexes) const +{ + return Utils::filtered( + Utils::transform(indexes, [this](const QModelIndex &i) { return task(i); }), + [](const Task &t) { return !t.isNull(); }); +} + QList TaskModel::categoryIds() const { QList categories = m_categories.keys(); @@ -360,6 +368,12 @@ void TaskFilterModel::setFilterIncludesWarnings(bool b) invalidateFilter(); } +Tasks TaskFilterModel::tasks(const QModelIndexList &indexes) const +{ + return taskModel()->tasks(Utils::transform(indexes, [this](const QModelIndex &i) { + return mapToSource(i); })); +} + int TaskFilterModel::issuesCount(int startRow, int endRow) const { int count = 0; diff --git a/src/plugins/projectexplorer/taskmodel.h b/src/plugins/projectexplorer/taskmodel.h index 43e2d1d18c9..a0f23710194 100644 --- a/src/plugins/projectexplorer/taskmodel.h +++ b/src/plugins/projectexplorer/taskmodel.h @@ -49,6 +49,7 @@ public: int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; Task task(const QModelIndex &index) const; + Tasks tasks(const QModelIndexList &indexes) const; QList categoryIds() const; QString categoryDisplayName(Utils::Id categoryId) const; @@ -142,6 +143,7 @@ public: void setFilteredCategories(const QList &categoryIds) { m_categoryIds = categoryIds; invalidateFilter(); } Task task(const QModelIndex &index) const { return taskModel()->task(mapToSource(index)); } + Tasks tasks(const QModelIndexList &indexes) const; int issuesCount(int startRow, int endRow) const; bool hasFile(const QModelIndex &index) const diff --git a/src/plugins/projectexplorer/taskwindow.cpp b/src/plugins/projectexplorer/taskwindow.cpp index 7b197a7ce18..5e446246b15 100644 --- a/src/plugins/projectexplorer/taskwindow.cpp +++ b/src/plugins/projectexplorer/taskwindow.cpp @@ -67,7 +67,7 @@ namespace ProjectExplorer { static QList g_taskHandlers; -ITaskHandler::ITaskHandler() +ITaskHandler::ITaskHandler(bool isMultiHandler) : m_isMultiHandler(isMultiHandler) { g_taskHandlers.append(this); } @@ -77,6 +77,30 @@ ITaskHandler::~ITaskHandler() g_taskHandlers.removeOne(this); } +void ITaskHandler::handle(const Task &task) +{ + QTC_ASSERT(m_isMultiHandler, return); + handle(Tasks{task}); +} + +void ITaskHandler::handle(const Tasks &tasks) +{ + QTC_ASSERT(canHandle(tasks), return); + QTC_ASSERT(!m_isMultiHandler, return); + handle(tasks.first()); +} + +bool ITaskHandler::canHandle(const Tasks &tasks) const +{ + if (tasks.isEmpty()) + return false; + if (m_isMultiHandler) + return true; + if (tasks.size() > 1) + return false; + return canHandle(tasks.first()); +} + namespace Internal { class TaskView : public Utils::ListView @@ -322,7 +346,7 @@ TaskWindow::TaskWindow() : d(std::make_unique()) d->m_listview->setModel(d->m_filter); d->m_listview->setFrameStyle(QFrame::NoFrame); d->m_listview->setWindowTitle(displayName()); - d->m_listview->setSelectionMode(QAbstractItemView::SingleSelection); + d->m_listview->setSelectionMode(QAbstractItemView::ExtendedSelection); auto *tld = new Internal::TaskDelegate(this); d->m_listview->setItemDelegate(tld); d->m_listview->setWindowIcon(Icons::WINDOW.icon()); @@ -336,11 +360,18 @@ TaskWindow::TaskWindow() : d(std::make_unique()) connect(d->m_listview->selectionModel(), &QItemSelectionModel::currentChanged, tld, &TaskDelegate::currentChanged); - connect(d->m_listview->selectionModel(), &QItemSelectionModel::currentChanged, - this, &TaskWindow::currentChanged); + this, [this](const QModelIndex &index) { d->m_listview->scrollTo(index); }); connect(d->m_listview, &QAbstractItemView::activated, this, &TaskWindow::triggerDefaultHandler); + connect(d->m_listview->selectionModel(), &QItemSelectionModel::selectionChanged, + this, [this] { + const Tasks tasks = d->m_filter->tasks(d->m_listview->selectionModel()->selectedIndexes()); + for (QAction * const action : qAsConst(d->m_actions)) { + ITaskHandler * const h = d->handler(action); + action->setEnabled(h && h->canHandle(tasks)); + } + }); d->m_contextMenu = new QMenu(d->m_listview); @@ -417,6 +448,7 @@ void TaskWindow::delayedInitialization() d->m_defaultHandler = h; QAction *action = h->createAction(this); + action->setEnabled(false); QTC_ASSERT(action, continue); d->m_actionToHandlerMap.insert(action, h); connect(action, &QAction::triggered, this, &TaskWindow::actionTriggered); @@ -430,9 +462,6 @@ void TaskWindow::delayedInitialization() } d->m_listview->addAction(action); } - - // Disable everything for now: - currentChanged(QModelIndex()); } QList TaskWindow::toolBarWidgets() const @@ -468,16 +497,6 @@ void TaskWindow::setCategoryVisibility(Utils::Id categoryId, bool visible) d->m_filter->setFilteredCategories(categories); } -void TaskWindow::currentChanged(const QModelIndex &index) -{ - const Task task = index.isValid() ? d->m_filter->task(index) : Task(); - foreach (QAction *action, d->m_actions) { - ITaskHandler *h = d->handler(action); - action->setEnabled((task.isNull() || !h) ? false : h->canHandle(task)); - } - d->m_listview->scrollTo(index); -} - void TaskWindow::saveSettings() { QStringList categories = Utils::transform(d->m_filter->filteredCategories(), &Utils::Id::toString); @@ -605,12 +624,7 @@ void TaskWindow::actionTriggered() if (!h) return; - QModelIndex index = d->m_listview->selectionModel()->currentIndex(); - Task task = d->m_filter->task(index); - if (task.isNull()) - return; - - h->handle(task); + h->handle(d->m_filter->tasks(d->m_listview->selectionModel()->selectedIndexes())); } void TaskWindow::setShowWarnings(bool show) @@ -774,11 +788,11 @@ QSize TaskDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelInd initStyleOption(&opt, index); auto view = qobject_cast(opt.widget); - const bool selected = (view->selectionModel()->currentIndex() == index); + const bool current = view->selectionModel()->currentIndex() == index; QSize s; s.setWidth(option.rect.width()); - if (!selected && option.font == m_cachedFont && m_cachedHeight > 0) { + if (!current && option.font == m_cachedFont && m_cachedHeight > 0) { s.setHeight(m_cachedHeight); return s; } @@ -790,7 +804,7 @@ QSize TaskDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelInd auto model = static_cast(view->model())->taskModel(); Positions positions(option, model); - if (selected) { + if (current) { QString description = index.data(TaskModel::Description).toString(); // Layout the description int leading = fontLeading; @@ -817,7 +831,7 @@ QSize TaskDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelInd if (s.height() < Positions::minimumHeight()) s.setHeight(Positions::minimumHeight()); - if (!selected) { + if (!current) { m_cachedHeight = s.height(); m_cachedFont = option.font; } @@ -856,7 +870,8 @@ void TaskDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, QColor textColor; auto view = qobject_cast(opt.widget); - bool selected = view->selectionModel()->currentIndex() == index; + const bool selected = view->selectionModel()->isSelected(index); + const bool current = view->selectionModel()->currentIndex() == index; if (selected) { painter->setBrush(opt.palette.highlight().color()); @@ -885,7 +900,7 @@ void TaskDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, icon.pixmap(Positions::taskIconWidth(), Positions::taskIconHeight())); // Paint TextArea: - if (!selected) { + if (!current) { // in small mode we lay out differently QString bottom = index.data(TaskModel::Description).toString().split(QLatin1Char('\n')).first(); painter->setClipRect(positions.textArea()); @@ -908,7 +923,7 @@ void TaskDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, QTextLayout tl(description); QVector formats = index.data(TaskModel::Task_t).value().formats; for (QTextLayout::FormatRange &format : formats) - format.format.setForeground(opt.palette.highlightedText()); + format.format.setForeground(textColor); tl.setFormats(formats); tl.beginLayout(); while (true) { diff --git a/src/plugins/projectexplorer/taskwindow.h b/src/plugins/projectexplorer/taskwindow.h index e3287a92bd5..30f75ed09d6 100644 --- a/src/plugins/projectexplorer/taskwindow.h +++ b/src/plugins/projectexplorer/taskwindow.h @@ -91,7 +91,6 @@ private: void openTask(const Task &task); void clearTasks(Utils::Id categoryId); void setCategoryVisibility(Utils::Id categoryId, bool visible); - void currentChanged(const QModelIndex &index); void saveSettings(); void loadSettings(); From c6fdb66b2bd5c1dd30220fb0e87d2fc2e0dc2615 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 24 Jan 2022 17:06:54 +0100 Subject: [PATCH 03/12] Collect Qt Creator debug menu items into common submenu instead of spreading them over the place. - rename "Logger..." to "Show Logs..." - create "Tools > Debug Qt Creator" menu and put "Show Logs", "Inspect Language Clients" and "Inspect C++ Code Model" there - add missing ellipsis That gets rid of the otherwise not useful "Language Client" submenu, and creates a nicer place for the "Show Logs" item. Change-Id: I2588b4c93327669579979dfbfce37005ada29dab Reviewed-by: Christian Kandeler --- .../src/editors/creator-coding-edit-mode.qdoc | 2 +- src/plugins/boot2qt/qdbplugin.cpp | 3 +-- src/plugins/coreplugin/coreconstants.h | 2 ++ src/plugins/coreplugin/mainwindow.cpp | 17 +++++++++++------ src/plugins/cppeditor/cppeditorplugin.cpp | 4 ++-- src/plugins/diffeditor/diffeditorplugin.cpp | 2 +- .../languageclient/languageclient_global.h | 1 - .../languageclient/languageclientplugin.cpp | 12 ++++-------- 8 files changed, 22 insertions(+), 21 deletions(-) diff --git a/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc b/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc index 1d1ef00d613..60fafe368bb 100644 --- a/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc +++ b/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc @@ -307,7 +307,7 @@ To view information about the C++ code model in the \uicontrol {C++ Code Model Inspector} dialog and write it to a log file, - select \uicontrol Tools > \uicontrol {C++} > + select \uicontrol Tools > \uicontrol {Debug \QC } > \uicontrol {Inspect C++ Code Model} or press \key {Ctrl+Shift+F12}. \QC generates the code model inspection log file in a temporary folder. diff --git a/src/plugins/boot2qt/qdbplugin.cpp b/src/plugins/boot2qt/qdbplugin.cpp index 875bd874a7a..b9b8aa237d7 100644 --- a/src/plugins/boot2qt/qdbplugin.cpp +++ b/src/plugins/boot2qt/qdbplugin.cpp @@ -109,8 +109,7 @@ void registerFlashAction(QObject *parentForAction) Core::ActionContainer *toolsContainer = Core::ActionManager::actionContainer(Core::Constants::M_TOOLS); - toolsContainer->insertGroup(Core::Constants::G_TOOLS_OPTIONS, - flashActionId); + toolsContainer->insertGroup(Core::Constants::G_TOOLS_DEBUG, flashActionId); Core::Context globalContext(Core::Constants::C_GLOBAL); diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h index ef0302293e9..96234c16c33 100644 --- a/src/plugins/coreplugin/coreconstants.h +++ b/src/plugins/coreplugin/coreconstants.h @@ -55,6 +55,7 @@ const char M_VIEW_VIEWS[] = "QtCreator.Menu.View.Views"; const char M_VIEW_PANES[] = "QtCreator.Menu.View.Panes"; const char M_TOOLS[] = "QtCreator.Menu.Tools"; const char M_TOOLS_EXTERNAL[] = "QtCreator.Menu.Tools.External"; +const char M_TOOLS_DEBUG[] = "QtCreator.Menu.Tools.Debug"; const char M_WINDOW[] = "QtCreator.Menu.Window"; const char M_HELP[] = "QtCreator.Menu.Help"; @@ -186,6 +187,7 @@ const char G_VIEW_VIEWS[] = "QtCreator.Group.View.Views"; const char G_VIEW_PANES[] = "QtCreator.Group.View.Panes"; // Tools menu groups +const char G_TOOLS_DEBUG[] = "QtCreator.Group.Tools.Debug"; const char G_TOOLS_OPTIONS[] = "QtCreator.Group.Tools.Options"; // Window menu groups diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp index f23c0040d3f..145244f7d85 100644 --- a/src/plugins/coreplugin/mainwindow.cpp +++ b/src/plugins/coreplugin/mainwindow.cpp @@ -701,16 +701,21 @@ void MainWindow::registerDefaultActions() cmd->setDefaultKeySequence(QKeySequence(Core::useMacShortcuts ? tr("Meta+0") : tr("Ctrl+0"))); tmpaction->setEnabled(false); + // Debug Qt Creator menu + mtools->appendGroup(Constants::G_TOOLS_DEBUG); + ActionContainer *mtoolsdebug = ActionManager::createMenu(Constants::M_TOOLS_DEBUG); + mtoolsdebug->menu()->setTitle(tr("Debug %1").arg(Constants::IDE_DISPLAY_NAME)); + mtools->addMenu(mtoolsdebug, Constants::G_TOOLS_DEBUG); + + m_loggerAction = new QAction(tr("Show Logs..."), this); + cmd = ActionManager::registerAction(m_loggerAction, Constants::LOGGER); + mtoolsdebug->addAction(cmd); + connect(m_loggerAction, &QAction::triggered, this, [] { LoggingViewer::showLoggingView(); }); + // Options Action mtools->appendGroup(Constants::G_TOOLS_OPTIONS); mtools->addSeparator(Constants::G_TOOLS_OPTIONS); - m_loggerAction = new QAction(tr("Logger..."), this); - cmd = ActionManager::registerAction(m_loggerAction, Constants::LOGGER); - mtools->addAction(cmd, Constants::G_TOOLS_OPTIONS); - connect(m_loggerAction, &QAction::triggered, this, [] { LoggingViewer::showLoggingView(); }); - mtools->addSeparator(Constants::G_TOOLS_OPTIONS); - m_optionsAction = new QAction(tr("&Options..."), this); m_optionsAction->setMenuRole(QAction::PreferencesRole); cmd = ActionManager::registerAction(m_optionsAction, Constants::OPTIONS); diff --git a/src/plugins/cppeditor/cppeditorplugin.cpp b/src/plugins/cppeditor/cppeditorplugin.cpp index 2ca9a96253f..2a8557b2981 100644 --- a/src/plugins/cppeditor/cppeditorplugin.cpp +++ b/src/plugins/cppeditor/cppeditorplugin.cpp @@ -413,12 +413,12 @@ bool CppEditorPlugin::initialize(const QStringList & /*arguments*/, QString *err cppModelManager, &CppModelManager::updateModifiedSourceFiles); cppToolsMenu->addAction(cmd, Core::Constants::G_DEFAULT_THREE); - cppToolsMenu->addSeparator(Core::Constants::G_DEFAULT_THREE); + ActionContainer *toolsDebug = ActionManager::actionContainer(Core::Constants::M_TOOLS_DEBUG); QAction *inspectCppCodeModel = new QAction(tr("Inspect C++ Code Model..."), this); cmd = ActionManager::registerAction(inspectCppCodeModel, Constants::INSPECT_CPP_CODEMODEL); cmd->setDefaultKeySequence(QKeySequence(useMacShortcuts ? tr("Meta+Shift+F12") : tr("Ctrl+Shift+F12"))); connect(inspectCppCodeModel, &QAction::triggered, d, &CppEditorPluginPrivate::inspectCppCodeModel); - cppToolsMenu->addAction(cmd, Core::Constants::G_DEFAULT_THREE); + toolsDebug->addAction(cmd); contextMenu->addSeparator(context); diff --git a/src/plugins/diffeditor/diffeditorplugin.cpp b/src/plugins/diffeditor/diffeditorplugin.cpp index 69863f91202..90cdb054220 100644 --- a/src/plugins/diffeditor/diffeditorplugin.cpp +++ b/src/plugins/diffeditor/diffeditorplugin.cpp @@ -472,7 +472,7 @@ DiffEditorPluginPrivate::DiffEditorPluginPrivate() //register actions ActionContainer *toolsContainer = ActionManager::actionContainer(Core::Constants::M_TOOLS); - toolsContainer->insertGroup(Core::Constants::G_TOOLS_OPTIONS, Constants::G_TOOLS_DIFF); + toolsContainer->insertGroup(Core::Constants::G_TOOLS_DEBUG, Constants::G_TOOLS_DIFF); ActionContainer *diffContainer = ActionManager::createMenu("Diff"); diffContainer->menu()->setTitle(tr("&Diff")); toolsContainer->addMenu(diffContainer, Constants::G_TOOLS_DIFF); diff --git a/src/plugins/languageclient/languageclient_global.h b/src/plugins/languageclient/languageclient_global.h index 8a63c660ac8..37556715372 100644 --- a/src/plugins/languageclient/languageclient_global.h +++ b/src/plugins/languageclient/languageclient_global.h @@ -48,7 +48,6 @@ const char LANGUAGECLIENT_WORKSPACE_CLASS_FILTER_ID[] = "Workspace Classes and S const char LANGUAGECLIENT_WORKSPACE_CLASS_FILTER_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("LanguageClient", "Classes and Structs in Workspace"); const char LANGUAGECLIENT_WORKSPACE_METHOD_FILTER_ID[] = "Workspace Functions and Methods"; const char LANGUAGECLIENT_WORKSPACE_METHOD_FILTER_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("LanguageClient", "Functions and Methods in Workspace"); -const char G_TOOLS_LANGUAGECLIENT[] = "QtCreator.Group.Tools.LanguageClient"; } // namespace Constants } // namespace LanguageClient diff --git a/src/plugins/languageclient/languageclientplugin.cpp b/src/plugins/languageclient/languageclientplugin.cpp index 8f530f70139..c8b4d134a0e 100644 --- a/src/plugins/languageclient/languageclientplugin.cpp +++ b/src/plugins/languageclient/languageclientplugin.cpp @@ -63,16 +63,12 @@ bool LanguageClientPlugin::initialize(const QStringList & /*arguments*/, QString []() { return new StdIOSettings; }}); //register actions - ActionContainer *toolsContainer - = ActionManager::actionContainer(Core::Constants::M_TOOLS); - toolsContainer->insertGroup(Core::Constants::G_TOOLS_OPTIONS, Constants::G_TOOLS_LANGUAGECLIENT); - ActionContainer *container = ActionManager::createMenu("Language Client"); - container->menu()->setTitle(tr("&Language Client")); - toolsContainer->addMenu(container, Constants::G_TOOLS_LANGUAGECLIENT); + ActionContainer *toolsDebugContainer = ActionManager::actionContainer( + Core::Constants::M_TOOLS_DEBUG); - auto inspectAction = new QAction(tr("Inspect Language Clients"), this); + auto inspectAction = new QAction(tr("Inspect Language Clients..."), this); connect(inspectAction, &QAction::triggered, this, &LanguageClientManager::showInspector); - container->addAction( + toolsDebugContainer->addAction( ActionManager::registerAction(inspectAction, "LanguageClient.InspectLanguageClients")); return true; From 3e1095076e2ecbf99115bce18c23ed194cc0810e Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Wed, 26 Jan 2022 13:31:46 +0100 Subject: [PATCH 04/12] QmlDesigner: Split image category only for dialog If we split the categories on the action level, then a separate dialog is opened for every image suffix/type. Task-number: QDS-6076 Change-Id: Ie80203cebca41e8dee4cb5c091b1163a9fde6e26 Reviewed-by: Miikka Heikkinen --- .../componentcore/designeractionmanager.cpp | 21 ++++---------- .../itemlibrary/itemlibrarywidget.cpp | 28 +++++++++++++++++-- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp index 89fa1d39d19..e160f030dbf 100644 --- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp +++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp @@ -1556,25 +1556,16 @@ void DesignerActionManager::createDefaultAddResourceHandler() // Having a single image type category creates too large of a filter, so we split images into // categories according to their mime types - const QList mimeTypes = QImageReader::supportedMimeTypes(); auto transformer = [](const QByteArray& format) -> QString { return QString("*.") + format; }; - QHash imageFormats; - for (const auto &mimeType : mimeTypes) - imageFormats.insert(mimeType, Utils::transform(QImageReader::imageFormatsForMimeType(mimeType), transformer)); - imageFormats.insert("image/vnd.radiance", {"*.hdr"}); - imageFormats.insert("image/ktx", {"*.ktx"}); + auto imageFormats = Utils::transform(QImageReader::supportedImageFormats(), transformer); + imageFormats.push_back("*.hdr"); + imageFormats.push_back("*.ktx"); // The filters will be displayed in reverse order to these lists in file dialog, // so declare most common types last - QHash::const_iterator i = imageFormats.constBegin(); - while (i != imageFormats.constEnd()) { - registerHandlers(i.value(), - ModelNodeOperations::addImageToProject, - QObject::tr("%1: %2") - .arg(ComponentCoreConstants::addImagesDisplayString) - .arg(QString::fromLatin1(i.key()))); - ++i; - } + registerHandlers(imageFormats, + ModelNodeOperations::addImageToProject, + ComponentCoreConstants::addImagesDisplayString); registerHandlers({"*.otf", "*.ttf"}, ModelNodeOperations::addFontToProject, ComponentCoreConstants::addFontsDisplayString); diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp index 75818fb42a4..10913090b46 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp @@ -596,6 +596,19 @@ void ItemLibraryWidget::addImportForItem(const QString &importUrl) m_model->changeImports({import}, {}); } +static QHash allImageFormats() +{ + const QList mimeTypes = QImageReader::supportedMimeTypes(); + auto transformer = [](const QByteArray& format) -> QString { return QString("*.") + format; }; + QHash imageFormats; + for (const auto &mimeType : mimeTypes) + imageFormats.insert(mimeType, Utils::transform(QImageReader::imageFormatsForMimeType(mimeType), transformer)); + imageFormats.insert("image/vnd.radiance", {"*.hdr"}); + imageFormats.insert("image/ktx", {"*.ktx"}); + + return imageFormats; +} + void ItemLibraryWidget::addResources(const QStringList &files) { DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument(); @@ -621,8 +634,19 @@ void ItemLibraryWidget::addResources(const QStringList &files) QStringList filters { tr("All Files (%1)").arg("*.*") }; QString filterTemplate = "%1 (%2)"; - for (const QString &key : qAsConst(sortedKeys)) - filters.append(filterTemplate.arg(key, map.values(key).join(' '))); + for (const QString &key : qAsConst(sortedKeys)) { + const QStringList values = map.values(key); + if (values.contains("*.png")) { // Avoid long filter for images by splitting + const QHash imageFormats = allImageFormats(); + QHash::const_iterator i = imageFormats.constBegin(); + while (i != imageFormats.constEnd()) { + filters.append(filterTemplate.arg(key + QString::fromLatin1(i.key()), i.value().join(' '))); + ++i; + } + } else { + filters.append(filterTemplate.arg(key, values.join(' '))); + } + } static QString lastDir; const QString currentDir = lastDir.isEmpty() ? document->fileName().parentDir().toString() : lastDir; From 1fc83d2a568dea3233212b351d6e9ffbc05c75e9 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 21 Jan 2022 12:22:54 +0100 Subject: [PATCH 05/12] Utils: Wrap various file system iteration flags and filters ... into a single class. This makes passing them around as a whole easier, and opens a path to have "generic" filters in form of a lambda or such. Change-Id: Ibf644b2fedcf0f1a35258030710afff8f5873f88 Reviewed-by: Qt CI Bot Reviewed-by: Eike Ziller --- src/libs/utils/buildablehelperlibrary.cpp | 4 +- src/libs/utils/filepath.cpp | 28 ++++++----- src/libs/utils/filepath.h | 20 +++++--- src/libs/utils/fileutils.h | 4 +- src/libs/utils/settingsaccessor.cpp | 2 +- src/plugins/android/androidconfigurations.cpp | 3 +- src/plugins/android/androidmanager.cpp | 2 +- .../androidmanifesteditoriconwidget.cpp | 2 +- src/plugins/android/androidsdkdownloader.cpp | 4 +- src/plugins/android/javalanguageserver.cpp | 2 +- .../cmakeprojectimporter.cpp | 2 +- .../cmakeprojectmanager/fileapiparser.cpp | 5 +- src/plugins/debugger/debuggeritemmanager.cpp | 2 +- src/plugins/debugger/gdb/gdbengine.cpp | 4 +- src/plugins/docker/dockerdevice.cpp | 47 ++++++++++--------- src/plugins/docker/dockerdevice.h | 7 +-- src/plugins/git/gerrit/gerritparameters.cpp | 2 +- src/plugins/mcusupport/mcusupportsdk.cpp | 14 +++--- .../devicesupport/desktopdevice.cpp | 8 ++-- .../devicesupport/desktopdevice.h | 4 +- .../devicesupport/devicemanager.cpp | 6 +-- .../projectexplorer/devicesupport/idevice.cpp | 8 +--- .../projectexplorer/devicesupport/idevice.h | 7 +-- src/plugins/projectexplorer/gcctoolchain.cpp | 3 +- .../jsonwizard/jsonwizardfactory.cpp | 11 +++-- .../projectexplorer/projectexplorer.cpp | 2 +- src/plugins/projectexplorer/session.cpp | 3 +- .../qmldesigner/generatecmakelists.cpp | 6 +-- src/plugins/qnx/qnxconfiguration.cpp | 5 +- src/plugins/qnx/qnxutils.cpp | 4 +- .../remotelinux/filesystemaccess_test.cpp | 3 +- src/plugins/remotelinux/linuxdevice.cpp | 27 +++++------ src/plugins/remotelinux/linuxdevice.h | 4 +- .../texteditor/highlightersettings.cpp | 6 +-- .../snippets/snippetscollection.cpp | 3 +- 35 files changed, 121 insertions(+), 143 deletions(-) diff --git a/src/libs/utils/buildablehelperlibrary.cpp b/src/libs/utils/buildablehelperlibrary.cpp index a4ab89fe89c..f5f5f5d39a4 100644 --- a/src/libs/utils/buildablehelperlibrary.cpp +++ b/src/libs/utils/buildablehelperlibrary.cpp @@ -88,9 +88,7 @@ static FilePath findQmakeInDir(const FilePath &dir) // Prefer qmake-qt5 to qmake-qt4 by sorting the filenames in reverse order. const FilePaths candidates = dir.dirEntries( - BuildableHelperLibrary::possibleQMakeCommands(), - QDir::Files, - QDirIterator::NoIteratorFlags, + {BuildableHelperLibrary::possibleQMakeCommands(), QDir::Files}, QDir::Name | QDir::Reversed); for (const FilePath &candidate : candidates) { if (candidate == qmakePath) diff --git a/src/libs/utils/filepath.cpp b/src/libs/utils/filepath.cpp index 2b665d0c84e..bcf713687a8 100644 --- a/src/libs/utils/filepath.cpp +++ b/src/libs/utils/filepath.cpp @@ -718,19 +718,16 @@ bool FilePath::createDir() const return dir.mkpath(dir.absolutePath()); } -FilePaths FilePath::dirEntries(const QStringList &nameFilters, - QDir::Filters filters, - QDirIterator::IteratorFlags flags, - QDir::SortFlags sort) const +FilePaths FilePath::dirEntries(const FileFilter &filter, QDir::SortFlags sort) const { FilePaths result; if (needsDevice()) { QTC_ASSERT(s_deviceHooks.iterateDirectory, return {}); const auto callBack = [&result](const FilePath &path) { result.append(path); return true; }; - s_deviceHooks.iterateDirectory(*this, callBack, nameFilters, filters, flags); + s_deviceHooks.iterateDirectory(*this, callBack, filter); } else { - QDirIterator dit(m_data, nameFilters, filters, flags); + QDirIterator dit(m_data, filter.nameFilters, filter.fileFilters, filter.iteratorFlags); while (dit.hasNext()) result.append(FilePath::fromString(dit.next())); } @@ -748,7 +745,7 @@ FilePaths FilePath::dirEntries(const QStringList &nameFilters, FilePaths FilePath::dirEntries(QDir::Filters filters) const { - return dirEntries({}, filters); + return dirEntries(FileFilter({}, filters)); } // This runs \a callBack on each directory entry matching all \a filters and @@ -756,17 +753,15 @@ FilePaths FilePath::dirEntries(QDir::Filters filters) const // An empty \nameFilters list matches every name. void FilePath::iterateDirectory(const std::function &callBack, - const QStringList &nameFilters, - QDir::Filters filters, - QDirIterator::IteratorFlags flags) const + const FileFilter &filter) const { if (needsDevice()) { QTC_ASSERT(s_deviceHooks.iterateDirectory, return); - s_deviceHooks.iterateDirectory(*this, callBack, nameFilters, filters, flags); + s_deviceHooks.iterateDirectory(*this, callBack, filter); return; } - QDirIterator it(m_data, nameFilters, filters, flags); + QDirIterator it(m_data, filter.nameFilters, filter.fileFilters, filter.iteratorFlags); while (it.hasNext()) { if (!callBack(FilePath::fromString(it.next()))) return; @@ -1454,6 +1449,15 @@ QTextStream &operator<<(QTextStream &s, const FilePath &fn) return s << fn.toString(); } +FileFilter::FileFilter(const QStringList &nameFilters, + const QDir::Filters fileFilters, + const QDirIterator::IteratorFlags flags) + : nameFilters(nameFilters), + fileFilters(fileFilters), + iteratorFlags(flags) +{ +} + } // namespace Utils std::hash::result_type diff --git a/src/libs/utils/filepath.h b/src/libs/utils/filepath.h index 2cb2ad9d92b..501feff17b0 100644 --- a/src/libs/utils/filepath.h +++ b/src/libs/utils/filepath.h @@ -51,6 +51,18 @@ namespace Utils { class Environment; class EnvironmentChange; +class QTCREATOR_UTILS_EXPORT FileFilter +{ +public: + FileFilter(const QStringList &nameFilters, + const QDir::Filters fileFilters = QDir::NoFilter, + const QDirIterator::IteratorFlags flags = QDirIterator::NoIteratorFlags); + + const QStringList nameFilters; + const QDir::Filters fileFilters = QDir::NoFilter; + const QDirIterator::IteratorFlags iteratorFlags = QDirIterator::NoIteratorFlags; +}; + class QTCREATOR_UTILS_EXPORT FilePath { public: @@ -121,9 +133,7 @@ public: qint64 fileSize() const; qint64 bytesAvailable() const; bool createDir() const; - QList dirEntries(const QStringList &nameFilters, - QDir::Filters filters = QDir::NoFilter, - QDirIterator::IteratorFlags flags = QDirIterator::NoIteratorFlags, + QList dirEntries(const FileFilter &filter, QDir::SortFlags sort = QDir::NoSort) const; QList dirEntries(QDir::Filters filters) const; QByteArray fileContents(qint64 maxSize = -1, qint64 offset = 0) const; @@ -160,9 +170,7 @@ public: [[nodiscard]] FilePath onDevice(const FilePath &deviceTemplate) const; [[nodiscard]] FilePath withNewPath(const QString &newPath) const; void iterateDirectory(const std::function &callBack, - const QStringList &nameFilters, - QDir::Filters filters = QDir::NoFilter, - QDirIterator::IteratorFlags flags = QDirIterator::NoIteratorFlags) const; + const FileFilter &filter) const; // makes sure that capitalization of directories is canonical // on Windows and macOS. This is rarely needed. diff --git a/src/libs/utils/fileutils.h b/src/libs/utils/fileutils.h index af56d2fb49a..163e762e511 100644 --- a/src/libs/utils/fileutils.h +++ b/src/libs/utils/fileutils.h @@ -82,9 +82,7 @@ public: std::function mapToDevicePath; std::function &, // Abort on 'false' return. - const QStringList &, - QDir::Filters, - QDirIterator::IteratorFlags)> iterateDirectory; + const FileFilter &)> iterateDirectory; std::function fileContents; std::function writeFileContents; std::function lastModified; diff --git a/src/libs/utils/settingsaccessor.cpp b/src/libs/utils/settingsaccessor.cpp index 43bb69402a1..7c847446f95 100644 --- a/src/libs/utils/settingsaccessor.cpp +++ b/src/libs/utils/settingsaccessor.cpp @@ -221,7 +221,7 @@ FilePaths BackUpStrategy::readFileCandidates(const FilePath &baseFileName) const const QStringList filter(baseFileName.fileName() + '*'); const FilePath baseFileDir = baseFileName.parentDir(); - return baseFileDir.dirEntries(filter, QDir::Files | QDir::Hidden | QDir::System); + return baseFileDir.dirEntries({filter, QDir::Files | QDir::Hidden | QDir::System}); } int BackUpStrategy::compare(const SettingsAccessor::RestoreData &data1, diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index bf86c19ed80..ca8e29eb383 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -382,8 +382,7 @@ QVector AndroidConfig::availableNdkPlatforms(const QtVersion *qtVersion) co .toInt()); return true; }, - {"android-*"}, - QDir::Dirs); + {{"android-*"}, QDir::Dirs}); Utils::sort(availableNdkPlatforms, std::greater<>()); return availableNdkPlatforms; diff --git a/src/plugins/android/androidmanager.cpp b/src/plugins/android/androidmanager.cpp index a256bf43c7b..5a4d2c2fe52 100644 --- a/src/plugins/android/androidmanager.cpp +++ b/src/plugins/android/androidmanager.cpp @@ -423,7 +423,7 @@ QString AndroidManager::apkDevicePreferredAbi(const Target *target) QStringList apkAbis; const FilePaths libsPaths = libsPath.dirEntries(QDir::Dirs | QDir::NoDotAndDotDot); for (const FilePath &abiDir : libsPaths) { - if (!abiDir.dirEntries(QStringList("*.so"), QDir::Files | QDir::NoDotAndDotDot).isEmpty()) + if (!abiDir.dirEntries({{"*.so"}, QDir::Files | QDir::NoDotAndDotDot}).isEmpty()) apkAbis << abiDir.fileName(); } return preferredAbi(apkAbis, target); diff --git a/src/plugins/android/androidmanifesteditoriconwidget.cpp b/src/plugins/android/androidmanifesteditoriconwidget.cpp index 1202c8ebc18..742c1fd631b 100644 --- a/src/plugins/android/androidmanifesteditoriconwidget.cpp +++ b/src/plugins/android/androidmanifesteditoriconwidget.cpp @@ -256,7 +256,7 @@ static QImage scaleWithoutStretching(const QImage& original, const QSize& target static bool similarFilesExist(const FilePath &path) { - const FilePaths entries = path.parentDir().dirEntries({path.completeBaseName() + ".*"}, {}); + const FilePaths entries = path.parentDir().dirEntries({{path.completeBaseName() + ".*"}}); return !entries.empty(); } diff --git a/src/plugins/android/androidsdkdownloader.cpp b/src/plugins/android/androidsdkdownloader.cpp index 59adbe50bdf..28837ca8d4e 100644 --- a/src/plugins/android/androidsdkdownloader.cpp +++ b/src/plugins/android/androidsdkdownloader.cpp @@ -73,9 +73,7 @@ static void setSdkFilesExecPermission( const FilePath &sdkExtractPath) } return true; }, - {"*"}, - QDir::Files, - QDirIterator::Subdirectories); + {{"*"}, QDir::Files, QDirIterator::Subdirectories}); } void AndroidSdkDownloader::downloadAndExtractSdk(const FilePath &jdkPath, const FilePath &sdkExtractPath) diff --git a/src/plugins/android/javalanguageserver.cpp b/src/plugins/android/javalanguageserver.cpp index 390a7296bff..4c06b296ebd 100644 --- a/src/plugins/android/javalanguageserver.cpp +++ b/src/plugins/android/javalanguageserver.cpp @@ -322,7 +322,7 @@ void JLSClient::updateProjectFiles() const FilePath androidJar = sdkLocation / QString("platforms/%2/android.jar") .arg(targetSDK); FilePaths libs = {androidJar}; - libs << packageSourceDir.pathAppended("libs").dirEntries({"*.jar"}, QDir::Files); + libs << packageSourceDir.pathAppended("libs").dirEntries({{"*.jar"}, QDir::Files}); generateProjectFile(projectDir, qtSrc, project()->displayName()); generateClassPathFile(projectDir, sourceDir, libs); } diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp index bb00d0b05d2..add008f756d 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectimporter.cpp @@ -79,7 +79,7 @@ static QStringList scanDirectory(const FilePath &path, const QString &prefix) QStringList result; qCDebug(cmInputLog) << "Scanning for directories matching" << prefix << "in" << path; - foreach (const FilePath &entry, path.dirEntries({prefix + "*"}, QDir::Dirs | QDir::NoDotAndDotDot)) { + foreach (const FilePath &entry, path.dirEntries({{prefix + "*"}, QDir::Dirs | QDir::NoDotAndDotDot})) { QTC_ASSERT(entry.isDir(), continue); result.append(entry.toString()); } diff --git a/src/plugins/cmakeprojectmanager/fileapiparser.cpp b/src/plugins/cmakeprojectmanager/fileapiparser.cpp index 863aec0c14e..3e0f1474a50 100644 --- a/src/plugins/cmakeprojectmanager/fileapiparser.cpp +++ b/src/plugins/cmakeprojectmanager/fileapiparser.cpp @@ -948,10 +948,7 @@ FilePath FileApiParser::scanForCMakeReplyFile(const FilePath &buildDirectory) if (!replyDir.exists()) return {}; - const FilePaths entries = replyDir.dirEntries({"index-*.json"}, - QDir::Files, - QDirIterator::NoIteratorFlags, - QDir::Name); + const FilePaths entries = replyDir.dirEntries({{"index-*.json"}, QDir::Files}, QDir::Name); return entries.isEmpty() ? FilePath() : entries.first(); } diff --git a/src/plugins/debugger/debuggeritemmanager.cpp b/src/plugins/debugger/debuggeritemmanager.cpp index 1b1e198d562..fbe0aeb3fac 100644 --- a/src/plugins/debugger/debuggeritemmanager.cpp +++ b/src/plugins/debugger/debuggeritemmanager.cpp @@ -780,7 +780,7 @@ void DebuggerItemManagerPrivate::autoDetectGdbOrLldbDebuggers(const FilePaths &s const auto addSuspect = [&suspects](const FilePath &entry) { suspects.append(entry); return true; }; for (const FilePath &path : paths) - path.iterateDirectory(addSuspect, filters, QDir::Files | QDir::Executable); + path.iterateDirectory(addSuspect, {filters, QDir::Files | QDir::Executable}); QStringList logMessages{tr("Searching debuggers...")}; for (const FilePath &command : qAsConst(suspects)) { diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 6aa84a68350..811f8d42e4e 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1615,9 +1615,7 @@ QString GdbEngine::cleanupFullName(const QString &fileName) } return true; }, - {"*"}, - QDir::NoFilter, - QDirIterator::Subdirectories); + {{"*"}, QDir::NoFilter, QDirIterator::Subdirectories}); } } diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp index 7cc8eaea073..26cbaf73e30 100644 --- a/src/plugins/docker/dockerdevice.cpp +++ b/src/plugins/docker/dockerdevice.cpp @@ -1455,17 +1455,20 @@ bool DockerDevice::setPermissions(const FilePath &filePath, QFileDevice::Permiss void DockerDevice::iterateWithFind(const FilePath &filePath, const std::function &callBack, - const QStringList &nameFilters, - QDir::Filters filters) const + const FileFilter &filter) const { QTC_ASSERT(callBack, return); QTC_CHECK(filePath.isAbsolutePath()); - QStringList arguments{filePath.path(), "-maxdepth", "1"}; + QStringList arguments{filePath.path()}; + + const QDir::Filters filters = filter.fileFilters; if (filters & QDir::NoSymLinks) arguments.prepend("-H"); else arguments.prepend("-L"); + if (!filter.iteratorFlags.testFlag(QDirIterator::Subdirectories)) + arguments.append({"-maxdepth", "1"}); QStringList filterOptions; if (filters & QDir::Dirs) @@ -1493,12 +1496,12 @@ void DockerDevice::iterateWithFind(const FilePath &filePath, const QString nameOption = (filters & QDir::CaseSensitive) ? QString{"-name"} : QString{"-iname"}; QStringList criticalWildcards; - if (!nameFilters.isEmpty()) { + if (!filter.nameFilters.isEmpty()) { const QRegularExpression oneChar("\\[.*?\\]"); - for (int i = 0, len = nameFilters.size(); i < len; ++i) { + for (int i = 0, len = filter.nameFilters.size(); i < len; ++i) { if (i > 0) filterOptions << "-o"; - QString current = nameFilters.at(i); + QString current = filter.nameFilters.at(i); if (current.indexOf(oneChar) != -1) criticalWildcards.append(current); current.replace(oneChar, "?"); // BAD! but still better than nothing @@ -1537,15 +1540,17 @@ void DockerDevice::iterateWithFind(const FilePath &filePath, static void filterEntriesHelper(const FilePath &base, const std::function &callBack, const QStringList &entries, - const QStringList &nameFilters, - QDir::Filters filters) + const FileFilter &filter) { - const QList nameRegexps = transform(nameFilters, [](const QString &filter) { - QRegularExpression re; - re.setPattern(QRegularExpression::wildcardToRegularExpression(filter)); - QTC_CHECK(re.isValid()); - return re; - }); + QTC_CHECK(filter.iteratorFlags != QDirIterator::NoIteratorFlags); // FIXME: Not supported yet below. + + const QList nameRegexps = + transform(filter.nameFilters, [](const QString &filter) { + QRegularExpression re; + re.setPattern(QRegularExpression::wildcardToRegularExpression(filter)); + QTC_CHECK(re.isValid()); + return re; + }); const auto nameMatches = [&nameRegexps](const QString &fileName) { for (const QRegularExpression &re : nameRegexps) { @@ -1557,7 +1562,7 @@ static void filterEntriesHelper(const FilePath &base, }; // FIXME: Handle filters. For now bark on unsupported options. - QTC_CHECK(filters == QDir::NoFilter); + QTC_CHECK(filter.fileFilters == QDir::NoFilter); for (const QString &entry : entries) { if (!nameMatches(entry)) @@ -1569,12 +1574,8 @@ static void filterEntriesHelper(const FilePath &base, void DockerDevice::iterateDirectory(const FilePath &filePath, const std::function &callBack, - const QStringList &nameFilters, - QDir::Filters filters, - QDirIterator::IteratorFlags flags) const + const FileFilter &filter) const { - Q_UNUSED(flags) // FIXME: Use it. - QTC_ASSERT(handlesFile(filePath), return); updateContainerAccess(); if (hasLocalFileAccess()) { @@ -1582,12 +1583,12 @@ void DockerDevice::iterateDirectory(const FilePath &filePath, local.iterateDirectory([&callBack, this](const FilePath &entry) { return callBack(mapFromLocalAccess(entry)); }, - nameFilters, filters); + filter); return; } if (d->m_useFind) { - iterateWithFind(filePath, callBack, nameFilters, filters); + iterateWithFind(filePath, callBack, filter); // d->m_useFind will be set to false if 'find' is not found. In this // case fall back to 'ls' below. if (d->m_useFind) @@ -1597,7 +1598,7 @@ void DockerDevice::iterateDirectory(const FilePath &filePath, // if we do not have find - use ls as fallback const QString output = d->outputForRunInShell({"ls", {"-1", "-b", "--", filePath.path()}}); const QStringList entries = output.split('\n', Qt::SkipEmptyParts); - filterEntriesHelper(filePath, callBack, entries, nameFilters, filters); + filterEntriesHelper(filePath, callBack, entries, filter); } QByteArray DockerDevice::fileContents(const FilePath &filePath, qint64 limit, qint64 offset) const diff --git a/src/plugins/docker/dockerdevice.h b/src/plugins/docker/dockerdevice.h index 310dd9e0d96..914fbabcb0e 100644 --- a/src/plugins/docker/dockerdevice.h +++ b/src/plugins/docker/dockerdevice.h @@ -96,9 +96,7 @@ public: Utils::FilePath symLinkTarget(const Utils::FilePath &filePath) const override; void iterateDirectory(const Utils::FilePath &filePath, const std::function &callBack, - const QStringList &nameFilters, - QDir::Filters filters, - QDirIterator::IteratorFlags flags = QDirIterator::NoIteratorFlags) const override; + const Utils::FileFilter &filter) const override; QByteArray fileContents(const Utils::FilePath &filePath, qint64 limit, qint64 offset) const override; bool writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const override; QDateTime lastModified(const Utils::FilePath &filePath) const override; @@ -127,8 +125,7 @@ protected: private: void iterateWithFind(const Utils::FilePath &filePath, const std::function &callBack, - const QStringList &nameFilters, - QDir::Filters filters) const; + const Utils::FileFilter &filter) const; void aboutToBeRemoved() const final; diff --git a/src/plugins/git/gerrit/gerritparameters.cpp b/src/plugins/git/gerrit/gerritparameters.cpp index 133fdaf02e3..75b76158c1a 100644 --- a/src/plugins/git/gerrit/gerritparameters.cpp +++ b/src/plugins/git/gerrit/gerritparameters.cpp @@ -70,7 +70,7 @@ static FilePath detectApp(const QString &defaultExe) if (!gitBinDir.endsWith("/usr/bin")) return {}; path = gitBinDir.parentDir().parentDir(); - const FilePaths entries = path.dirEntries({"mingw*"}, {}); + const FilePaths entries = path.dirEntries({{"mingw*"}}); if (entries.isEmpty()) return {}; path = entries.first() / "bin" / defaultApp; diff --git a/src/plugins/mcusupport/mcusupportsdk.cpp b/src/plugins/mcusupport/mcusupportsdk.cpp index d23147ee83a..44ad3c2356e 100644 --- a/src/plugins/mcusupport/mcusupportsdk.cpp +++ b/src/plugins/mcusupport/mcusupportsdk.cpp @@ -217,8 +217,7 @@ static McuPackage *createRGLPackage() if (rglPath.exists()) { defaultPath = rglPath; const FilePaths subDirs = - defaultPath.dirEntries({QLatin1String("rgl_ghs_D1Mx_*")}, - QDir::Dirs | QDir::NoDotAndDotDot); + defaultPath.dirEntries({{"rgl_ghs_D1Mx_*"}, QDir::Dirs | QDir::NoDotAndDotDot}); if (subDirs.count() == 1) defaultPath = subDirs.first(); } @@ -272,8 +271,7 @@ static McuPackage *createMcuXpressoIdePackage() defaultPath = programPath; // If default dir has exactly one sub dir that could be the IDE path, pre-select that. const FilePaths subDirs = - defaultPath.dirEntries({QLatin1String("MCUXpressoIDE*")}, - QDir::Dirs | QDir::NoDotAndDotDot); + defaultPath.dirEntries({{"MCUXpressoIDE*"}, QDir::Dirs | QDir::NoDotAndDotDot}); if (subDirs.count() == 1) defaultPath = subDirs.first(); } @@ -304,8 +302,8 @@ static McuPackage *createCypressProgrammerPackage() const FilePath candidate = findInProgramFiles("Cypress"); if (candidate.exists()) { // "Cypress Auto Flash Utility 1.0" - const auto subDirs = candidate.dirEntries({"Cypress Auto Flash Utility*"}, - QDir::Dirs, QDirIterator::NoIteratorFlags, QDir::Unsorted); + const auto subDirs = candidate.dirEntries({{"Cypress Auto Flash Utility*"}, QDir::Dirs}, + QDir::Unsorted); if (!subDirs.empty()) defaultPath = subDirs.first(); } @@ -331,8 +329,8 @@ static McuPackage *createRenesasProgrammerPackage() const FilePath candidate = findInProgramFiles("Renesas Electronics/Programming Tools"); if (candidate.exists()) { // "Renesas Flash Programmer V3.09" - const auto subDirs = candidate.dirEntries({"Renesas Flash Programmer*"}, - QDir::Dirs, QDirIterator::NoIteratorFlags, QDir::Unsorted); + const auto subDirs = candidate.dirEntries({{"Renesas Flash Programmer*"}, QDir::Dirs}, + QDir::Unsorted); if (!subDirs.empty()) defaultPath = subDirs.first(); } diff --git a/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp b/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp index 3a5c209dda7..33969239f76 100644 --- a/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp +++ b/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp @@ -177,13 +177,11 @@ bool DesktopDevice::handlesFile(const FilePath &filePath) const } void DesktopDevice::iterateDirectory(const FilePath &filePath, - const std::function &callBack, - const QStringList &nameFilters, - QDir::Filters filters, - QDirIterator::IteratorFlags flags) const + const std::function &callBack, + const FileFilter &filter) const { QTC_CHECK(!filePath.needsDevice()); - filePath.iterateDirectory(callBack, nameFilters, filters, flags); + filePath.iterateDirectory(callBack, filter); } qint64 DesktopDevice::fileSize(const FilePath &filePath) const diff --git a/src/plugins/projectexplorer/devicesupport/desktopdevice.h b/src/plugins/projectexplorer/devicesupport/desktopdevice.h index 4523be31bda..06502c559d6 100644 --- a/src/plugins/projectexplorer/devicesupport/desktopdevice.h +++ b/src/plugins/projectexplorer/devicesupport/desktopdevice.h @@ -75,9 +75,7 @@ public: Utils::FilePath symLinkTarget(const Utils::FilePath &filePath) const override; void iterateDirectory(const Utils::FilePath &filePath, const std::function &callBack, - const QStringList &nameFilters, - QDir::Filters filters, - QDirIterator::IteratorFlags flags) const override; + const Utils::FileFilter &filter) const override; QByteArray fileContents(const Utils::FilePath &filePath, qint64 limit, qint64 offset) const override; bool writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const override; qint64 fileSize(const Utils::FilePath &filePath) const override; diff --git a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp index 8eb992a88bd..32c6add09c1 100644 --- a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp +++ b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp @@ -524,12 +524,10 @@ DeviceManager::DeviceManager(bool isInstance) : d(std::make_unique &callBack, - const QStringList &nameFilters, - QDir::Filters filters, - QDirIterator::IteratorFlags flags) { + const FileFilter &filter) { auto device = DeviceManager::deviceForPath(filePath); QTC_ASSERT(device, return); - device->iterateDirectory(filePath, callBack, nameFilters, filters, flags); + device->iterateDirectory(filePath, callBack, filter); }; deviceHooks.fileContents = [](const FilePath &filePath, qint64 maxSize, qint64 offset) { diff --git a/src/plugins/projectexplorer/devicesupport/idevice.cpp b/src/plugins/projectexplorer/devicesupport/idevice.cpp index b183e38edfc..f9c91dea1a0 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.cpp +++ b/src/plugins/projectexplorer/devicesupport/idevice.cpp @@ -363,15 +363,11 @@ FilePath IDevice::symLinkTarget(const FilePath &filePath) const void IDevice::iterateDirectory(const FilePath &filePath, const std::function &callBack, - const QStringList &nameFilters, - QDir::Filters filters, - QDirIterator::IteratorFlags flags) const + const FileFilter &filter) const { Q_UNUSED(filePath); Q_UNUSED(callBack); - Q_UNUSED(nameFilters); - Q_UNUSED(filters); - Q_UNUSED(flags); + Q_UNUSED(filter); QTC_CHECK(false); } diff --git a/src/plugins/projectexplorer/devicesupport/idevice.h b/src/plugins/projectexplorer/devicesupport/idevice.h index 75491f94fcc..7b7f1e572e4 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.h +++ b/src/plugins/projectexplorer/devicesupport/idevice.h @@ -33,7 +33,6 @@ #include #include -#include #include #include #include @@ -257,13 +256,11 @@ public: virtual bool renameFile(const Utils::FilePath &filePath, const Utils::FilePath &target) const; virtual Utils::FilePath searchExecutableInPath(const QString &fileName) const; virtual Utils::FilePath searchExecutable(const QString &fileName, - const QList &dirs) const; + const Utils::FilePaths &dirs) const; virtual Utils::FilePath symLinkTarget(const Utils::FilePath &filePath) const; virtual void iterateDirectory(const Utils::FilePath &filePath, const std::function &callBack, - const QStringList &nameFilters, - QDir::Filters filters, - QDirIterator::IteratorFlags flags = QDirIterator::NoIteratorFlags) const; + const Utils::FileFilter &filter) const; virtual QByteArray fileContents(const Utils::FilePath &filePath, qint64 limit, qint64 offset) const; diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index b0b9809683f..5a83af5401e 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -1126,7 +1126,8 @@ static FilePaths findCompilerCandidates(const IDevice::ConstPtr &device, return true; }; const FilePath globalDir = device->mapToGlobalPath(deviceDir); - device->iterateDirectory(globalDir, callBack, nameFilters, QDir::Files | QDir::Executable); + device->iterateDirectory(globalDir, callBack, + {nameFilters, QDir::Files | QDir::Executable}); } } else { // The normal, local host case. diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp index 6f182cc1e4b..705e51aa66d 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp +++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp @@ -423,10 +423,11 @@ QList JsonWizardFactory::createWizardFactories() continue; } - const QDir::Filters filters = QDir::Dirs|QDir::Readable|QDir::NoDotAndDotDot; + const FileFilter filter { + {}, QDir::Dirs|QDir::Readable|QDir::NoDotAndDotDot, QDirIterator::NoIteratorFlags + }; const QDir::SortFlags sortflags = QDir::Name|QDir::IgnoreCase; - const QDirIterator::IteratorFlag iteratorFlags = QDirIterator::NoIteratorFlags; - FilePaths dirs = path.dirEntries({}, filters, iteratorFlags, sortflags); + FilePaths dirs = path.dirEntries(filter, sortflags); while (!dirs.isEmpty()) { const FilePath currentDir = dirs.takeFirst(); @@ -483,7 +484,7 @@ QList JsonWizardFactory::createWizardFactories() result << factory; } else { - FilePaths subDirs = currentDir.dirEntries({}, filters, iteratorFlags, sortflags); + FilePaths subDirs = currentDir.dirEntries(filter, sortflags); if (!subDirs.isEmpty()) { // There is no QList::prepend(QList)... dirs.swap(subDirs); @@ -579,7 +580,7 @@ static QString qmlProjectName(const FilePath &folder) { FilePath currentFolder = folder; while (!currentFolder.isEmpty()) { - const QList fileList = currentFolder.dirEntries({"*.qmlproject"}); + const FilePaths fileList = currentFolder.dirEntries({{"*.qmlproject"}}); if (!fileList.isEmpty()) return fileList.first().baseName(); currentFolder = currentFolder.parentDir(); diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 9efd7f2858b..f869a9d3cd4 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -694,7 +694,7 @@ static ProjectExplorerPluginPrivate *dd = nullptr; static FilePaths projectFilesInDirectory(const FilePath &path) { - return path.dirEntries(ProjectExplorerPlugin::projectFileGlobs(), QDir::Files); + return path.dirEntries({ProjectExplorerPlugin::projectFileGlobs(), QDir::Files}); } static FilePaths projectsInDirectory(const FilePath &filePath) diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp index c62d8796754..bd48cc84daf 100644 --- a/src/plugins/projectexplorer/session.cpp +++ b/src/plugins/projectexplorer/session.cpp @@ -791,8 +791,7 @@ QStringList SessionManager::sessions() { if (d->m_sessions.isEmpty()) { // We are not initialized yet, so do that now - const FilePaths sessionFiles = ICore::userResourcePath().dirEntries({"*.qws"}, - QDir::NoFilter, QDirIterator::NoIteratorFlags, QDir::Time); + const FilePaths sessionFiles = ICore::userResourcePath().dirEntries({{"*qws"}}, QDir::Time); for (const FilePath &file : sessionFiles) { const QString &name = file.completeBaseName(); d->m_sessionDateTimes.insert(name, file.lastModified()); diff --git a/src/plugins/qmldesigner/generatecmakelists.cpp b/src/plugins/qmldesigner/generatecmakelists.cpp index 7609a31c15c..c11f20436ca 100644 --- a/src/plugins/qmldesigner/generatecmakelists.cpp +++ b/src/plugins/qmldesigner/generatecmakelists.cpp @@ -354,7 +354,7 @@ void generateModuleCmake(const FilePath &dir, const QString &uri) QString fileTemplate = GenerateCmake::readTemplate(MODULEFILE_TEMPLATE_PATH); QString singletonContent; - FilePaths qmldirFileList = dir.dirEntries(QStringList(FILENAME_QMLDIR), FILES_ONLY); + FilePaths qmldirFileList = dir.dirEntries({QStringList(FILENAME_QMLDIR), FILES_ONLY}); if (!qmldirFileList.isEmpty()) { QStringList singletons = getSingletonsFromQmldirFile(qmldirFileList.first()); for (QString &singleton : singletons) { @@ -418,7 +418,7 @@ FilePaths getDirectoryQmls(const FilePath &dir) { const QStringList qmlFilesOnly("*.qml"); ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); - FilePaths allFiles = dir.dirEntries(qmlFilesOnly, FILES_ONLY); + FilePaths allFiles = dir.dirEntries({qmlFilesOnly, FILES_ONLY}); FilePaths moduleFiles; for (FilePath &file : allFiles) { if (!isFileBlacklisted(file.fileName()) && @@ -436,7 +436,7 @@ QStringList getDirectoryTreeQmls(const FilePath &dir) ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); QStringList qmlFileList; - FilePaths thisDirFiles = dir.dirEntries(qmlFilesOnly, FILES_ONLY); + FilePaths thisDirFiles = dir.dirEntries({qmlFilesOnly, FILES_ONLY}); for (FilePath &file : thisDirFiles) { if (!isFileBlacklisted(file.fileName()) && project->isKnownFile(file)) { diff --git a/src/plugins/qnx/qnxconfiguration.cpp b/src/plugins/qnx/qnxconfiguration.cpp index 9e5fbd25ec3..751bab34013 100644 --- a/src/plugins/qnx/qnxconfiguration.cpp +++ b/src/plugins/qnx/qnxconfiguration.cpp @@ -444,9 +444,8 @@ void QnxConfiguration::updateTargets() void QnxConfiguration::assignDebuggersToTargets() { const FilePath hostUsrBinDir = m_qnxHost.pathAppended("usr/bin"); - FilePaths debuggerNames = hostUsrBinDir.dirEntries( - QStringList(HostOsInfo::withExecutableSuffix("nto*-gdb")), - QDir::Files); + const FilePaths debuggerNames = hostUsrBinDir.dirEntries( + {{HostOsInfo::withExecutableSuffix("nto*-gdb")}, QDir::Files}); Environment sysEnv = Environment::systemEnvironment(); sysEnv.modify(qnxEnvironmentItems()); for (const FilePath &debuggerPath : debuggerNames) { diff --git a/src/plugins/qnx/qnxutils.cpp b/src/plugins/qnx/qnxutils.cpp index e8fabfb959b..90e3aeb8518 100644 --- a/src/plugins/qnx/qnxutils.cpp +++ b/src/plugins/qnx/qnxutils.cpp @@ -144,9 +144,9 @@ FilePath QnxUtils::envFilePath(const FilePath &sdpPath) { FilePaths entries; if (sdpPath.osType() == OsTypeWindows) - entries = sdpPath.dirEntries({"*-env.bat"}); + entries = sdpPath.dirEntries({{"*-env.bat"}}); else - entries = sdpPath.dirEntries({"*-env.sh"}); + entries = sdpPath.dirEntries({{"*-env.sh"}}); if (!entries.isEmpty()) return entries.first(); diff --git a/src/plugins/remotelinux/filesystemaccess_test.cpp b/src/plugins/remotelinux/filesystemaccess_test.cpp index 5d45484a7d3..603cd1b8782 100644 --- a/src/plugins/remotelinux/filesystemaccess_test.cpp +++ b/src/plugins/remotelinux/filesystemaccess_test.cpp @@ -114,8 +114,7 @@ void FileSystemAccessTest::testDirStatuses() } return false; }, - {"test"}, - QDir::Files); + {{"test"}, QDir::Files}); QVERIFY(fileExists); QVERIFY(testFilePath.removeFile()); diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp index 91c58bff1ea..5422d8d9130 100644 --- a/src/plugins/remotelinux/linuxdevice.cpp +++ b/src/plugins/remotelinux/linuxdevice.cpp @@ -679,16 +679,15 @@ bool LinuxDevice::setPermissions(const Utils::FilePath &filePath, QFileDevice::P static void filterEntriesHelper(const FilePath &base, const std::function &callBack, const QStringList &entries, - const QStringList &nameFilters, - QDir::Filters filters, - QDirIterator::IteratorFlags flags) + const FileFilter &filter) { - const QList nameRegexps = transform(nameFilters, [](const QString &filter) { - QRegularExpression re; - re.setPattern(QRegularExpression::wildcardToRegularExpression(filter)); - QTC_CHECK(re.isValid()); - return re; - }); + const QList nameRegexps = + transform(filter.nameFilters, [](const QString &filter) { + QRegularExpression re; + re.setPattern(QRegularExpression::wildcardToRegularExpression(filter)); + QTC_CHECK(re.isValid()); + return re; + }); const auto nameMatches = [&nameRegexps](const QString &fileName) { for (const QRegularExpression &re : nameRegexps) { @@ -700,8 +699,8 @@ static void filterEntriesHelper(const FilePath &base, }; // FIXME: Handle filters. For now bark on unsupported options. - QTC_CHECK(filters == QDir::NoFilter); - QTC_CHECK(flags == QDirIterator::NoIteratorFlags); + QTC_CHECK(filter.fileFilters == QDir::NoFilter); + QTC_CHECK(filter.iteratorFlags == QDirIterator::NoIteratorFlags); for (const QString &entry : entries) { if (!nameMatches(entry)) @@ -713,15 +712,13 @@ static void filterEntriesHelper(const FilePath &base, void LinuxDevice::iterateDirectory(const FilePath &filePath, const std::function &callBack, - const QStringList &nameFilters, - QDir::Filters filters, - QDirIterator::IteratorFlags flags) const + const FileFilter &filter) const { QTC_ASSERT(handlesFile(filePath), return); // if we do not have find - use ls as fallback const QString output = d->outputForRunInShell({"ls", {"-1", "-b", "--", filePath.path()}}); const QStringList entries = output.split('\n', Qt::SkipEmptyParts); - filterEntriesHelper(filePath, callBack, entries, nameFilters, filters, flags); + filterEntriesHelper(filePath, callBack, entries, filter); } QByteArray LinuxDevice::fileContents(const FilePath &filePath, qint64 limit, qint64 offset) const diff --git a/src/plugins/remotelinux/linuxdevice.h b/src/plugins/remotelinux/linuxdevice.h index 189b0229ecc..fa68624cacf 100644 --- a/src/plugins/remotelinux/linuxdevice.h +++ b/src/plugins/remotelinux/linuxdevice.h @@ -78,9 +78,7 @@ public: Utils::FilePath symLinkTarget(const Utils::FilePath &filePath) const override; void iterateDirectory(const Utils::FilePath &filePath, const std::function &callBack, - const QStringList &nameFilters, - QDir::Filters filters, - QDirIterator::IteratorFlags flags) const override; + const Utils::FileFilter &filter) const override; QByteArray fileContents(const Utils::FilePath &filePath, qint64 limit, qint64 offset) const override; bool writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const override; QDateTime lastModified(const Utils::FilePath &filePath) const override; diff --git a/src/plugins/texteditor/highlightersettings.cpp b/src/plugins/texteditor/highlightersettings.cpp index f94a5c09e12..75875249b7a 100644 --- a/src/plugins/texteditor/highlightersettings.cpp +++ b/src/plugins/texteditor/highlightersettings.cpp @@ -58,7 +58,7 @@ FilePath findFallbackDefinitionsLocation() FilePath("/opt") / kateSyntaxPath }; for (const FilePath &path : paths) { - if (path.exists() && !path.dirEntries({"*.xml"}).isEmpty()) + if (path.exists() && !path.dirEntries({{"*.xml"}}).isEmpty()) return path; } } @@ -76,7 +76,7 @@ FilePath findFallbackDefinitionsLocation() const FilePath dir = FilePath::fromString(output); for (auto &kateSyntaxPath : kateSyntaxPaths) { const FilePath path = dir / kateSyntaxPath; - if (path.exists() && !path.dirEntries({"*.xml"}).isEmpty()) + if (path.exists() && !path.dirEntries({{"*.xml"}}).isEmpty()) return path; } } @@ -84,7 +84,7 @@ FilePath findFallbackDefinitionsLocation() } const FilePath dir = Core::ICore::resourcePath("generic-highlighter"); - if (dir.exists() && !dir.dirEntries({"*.xml"}).isEmpty()) + if (dir.exists() && !dir.dirEntries({{"*.xml"}}).isEmpty()) return dir; return {}; diff --git a/src/plugins/texteditor/snippets/snippetscollection.cpp b/src/plugins/texteditor/snippets/snippetscollection.cpp index e678a93ef25..49ededc1b01 100644 --- a/src/plugins/texteditor/snippets/snippetscollection.cpp +++ b/src/plugins/texteditor/snippets/snippetscollection.cpp @@ -95,7 +95,8 @@ SnippetsCollection *SnippetsCollection::instance() // SnippetsCollection SnippetsCollection::SnippetsCollection() : m_userSnippetsFile(Core::ICore::userResourcePath("snippets/snippets.xml")), - m_builtInSnippetsFiles(Core::ICore::resourcePath("snippets").dirEntries({"*.xml"})) + m_builtInSnippetsFiles(Core::ICore::resourcePath("snippets") + .dirEntries(FileFilter({"*.xml"}))) { connect(Core::ICore::instance(), &Core::ICore::coreOpened, From f6cb6383457ccf8021b2df7e7cd9d760dcfc9fea Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 26 Jan 2022 13:02:49 +0100 Subject: [PATCH 06/12] ProjectExplorer: Make Tasks a QList, not a QVector That's what it is going to be in Qt6 anyways. Change-Id: I8a059fc0e4d8bb5a1e3138071613b1d72a08d15b Reviewed-by: Christian Stenger --- src/plugins/docker/dockerdevice.h | 2 +- src/plugins/projectexplorer/devicesupport/idevice.cpp | 2 +- src/plugins/projectexplorer/devicesupport/idevice.h | 2 +- src/plugins/projectexplorer/task.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/docker/dockerdevice.h b/src/plugins/docker/dockerdevice.h index 914fbabcb0e..1846c4f95f0 100644 --- a/src/plugins/docker/dockerdevice.h +++ b/src/plugins/docker/dockerdevice.h @@ -62,7 +62,7 @@ public: static Ptr create(const DockerDeviceData &data) { return Ptr(new DockerDevice(data)); } ProjectExplorer::IDeviceWidget *createWidget() override; - QVector validate() const override; + QList validate() const override; bool canCreateProcess() const override { return true; } ProjectExplorer::DeviceProcess *createProcess(QObject *parent) const override; diff --git a/src/plugins/projectexplorer/devicesupport/idevice.cpp b/src/plugins/projectexplorer/devicesupport/idevice.cpp index f9c91dea1a0..4977cafac41 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.cpp +++ b/src/plugins/projectexplorer/devicesupport/idevice.cpp @@ -543,7 +543,7 @@ bool IDevice::isCompatibleWith(const Kit *k) const return DeviceTypeKitAspect::deviceTypeId(k) == type(); } -QVector IDevice::validate() const +QList IDevice::validate() const { return {}; } diff --git a/src/plugins/projectexplorer/devicesupport/idevice.h b/src/plugins/projectexplorer/devicesupport/idevice.h index 7b7f1e572e4..144daffbfda 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.h +++ b/src/plugins/projectexplorer/devicesupport/idevice.h @@ -159,7 +159,7 @@ public: Utils::Id id() const; virtual bool isCompatibleWith(const Kit *k) const; - virtual QVector validate() const; + virtual QList validate() const; QString displayType() const; Utils::OsType osType() const; diff --git a/src/plugins/projectexplorer/task.h b/src/plugins/projectexplorer/task.h index 52cebcfc04a..1e9aa84dbb5 100644 --- a/src/plugins/projectexplorer/task.h +++ b/src/plugins/projectexplorer/task.h @@ -138,7 +138,7 @@ public: DeploymentTask(TaskType type, const QString &description); }; -using Tasks = QVector; +using Tasks = QList; PROJECTEXPLORER_EXPORT QString toHtml(const Tasks &issues); PROJECTEXPLORER_EXPORT bool containsType(const Tasks &issues, Task::TaskType); From 2b6f26dee2ba9429c405b829cea535d2ce906b72 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 26 Jan 2022 09:05:35 +0100 Subject: [PATCH 07/12] ProjectExplorer: Use a lambda for DeviceFactory::create() Somewhat slimmer interface on the user code side and follows existing practice. Change-Id: I20ed8f5a00591265d32ea9ce93e1f1bbc76d2437 Reviewed-by: Christian Kandeler --- src/plugins/android/androiddevice.cpp | 35 +++++++++--------- src/plugins/android/androiddevice.h | 1 - src/plugins/baremetal/baremetaldevice.cpp | 16 ++++----- src/plugins/baremetal/baremetaldevice.h | 4 +-- src/plugins/boot2qt/qdbdevice.cpp | 17 ++++----- src/plugins/boot2qt/qdbdevice.h | 3 -- src/plugins/docker/dockerdevice.cpp | 36 +++++++++---------- src/plugins/docker/dockerdevice.h | 2 -- src/plugins/mcusupport/mcusupportdevice.cpp | 8 ++--- src/plugins/mcusupport/mcusupportdevice.h | 2 -- .../devicesupport/idevicefactory.cpp | 10 ++++++ .../devicesupport/idevicefactory.h | 5 +-- src/plugins/qnx/qnxdevice.cpp | 19 +++++----- src/plugins/qnx/qnxdevice.h | 2 -- .../remotelinux/filesystemaccess_test.cpp | 24 ++++++------- .../remotelinux/filesystemaccess_test.h | 2 -- src/plugins/remotelinux/linuxdevice.cpp | 18 +++++----- src/plugins/remotelinux/linuxdevice.h | 2 -- src/plugins/webassembly/webassemblydevice.cpp | 13 +++---- src/plugins/webassembly/webassemblydevice.h | 2 -- 20 files changed, 96 insertions(+), 125 deletions(-) diff --git a/src/plugins/android/androiddevice.cpp b/src/plugins/android/androiddevice.cpp index 8f923146f5b..7a59abea961 100644 --- a/src/plugins/android/androiddevice.cpp +++ b/src/plugins/android/androiddevice.cpp @@ -663,34 +663,33 @@ AndroidDeviceManager::AndroidDeviceManager(QObject *parent) } // Factory + AndroidDeviceFactory::AndroidDeviceFactory() - : ProjectExplorer::IDeviceFactory(Constants::ANDROID_DEVICE_TYPE), + : IDeviceFactory(Constants::ANDROID_DEVICE_TYPE), m_androidConfig(AndroidConfigurations::currentConfig()) { setDisplayName(AndroidDevice::tr("Android Device")); setCombinedIcon(":/android/images/androiddevicesmall.png", ":/android/images/androiddevice.png"); + setConstructionFunction(&AndroidDevice::create); setCanCreate(m_androidConfig.sdkToolsOk()); -} + setCreator([this] { + AvdDialog dialog = AvdDialog(m_androidConfig, Core::ICore::dialogParent()); + if (dialog.exec() != QDialog::Accepted) + return IDevice::Ptr(); -IDevice::Ptr AndroidDeviceFactory::create() const -{ - AvdDialog dialog = AvdDialog(m_androidConfig, Core::ICore::dialogParent()); - if (dialog.exec() != QDialog::Accepted) - return ProjectExplorer::IDevice::Ptr(); + const IDevice::Ptr dev = dialog.device(); + if (const auto androidDev = static_cast(dev.data())) { + qCDebug(androidDeviceLog, "Created new Android AVD id \"%s\".", + qPrintable(androidDev->avdName())); + } else { + AndroidDeviceWidget::criticalDialog( + AndroidDevice::tr("The device info returned from AvdDialog is invalid.")); + } - const ProjectExplorer::IDevice::Ptr dev = dialog.device(); - const AndroidDevice *androidDev = static_cast(dev.data()); - if (androidDev) { - qCDebug(androidDeviceLog, "Created new Android AVD id \"%s\".", - qPrintable(androidDev->avdName())); - } else { - AndroidDeviceWidget::criticalDialog( - QObject::tr("The device info returned from AvdDialog is invalid.")); - } - - return IDevice::Ptr(dev); + return IDevice::Ptr(dev); + }); } } // namespace Internal diff --git a/src/plugins/android/androiddevice.h b/src/plugins/android/androiddevice.h index e98d4c003bb..3d08f09315c 100644 --- a/src/plugins/android/androiddevice.h +++ b/src/plugins/android/androiddevice.h @@ -88,7 +88,6 @@ class AndroidDeviceFactory final : public ProjectExplorer::IDeviceFactory { public: AndroidDeviceFactory(); - ProjectExplorer::IDevice::Ptr create() const override; private: const AndroidConfig &m_androidConfig; diff --git a/src/plugins/baremetal/baremetaldevice.cpp b/src/plugins/baremetal/baremetaldevice.cpp index cf06c500ab0..c5679898c84 100644 --- a/src/plugins/baremetal/baremetaldevice.cpp +++ b/src/plugins/baremetal/baremetaldevice.cpp @@ -125,16 +125,14 @@ BareMetalDeviceFactory::BareMetalDeviceFactory() setDisplayName(BareMetalDevice::tr("Bare Metal Device")); setCombinedIcon(":/baremetal/images/baremetaldevicesmall.png", ":/baremetal/images/baremetaldevice.png"); - setCanCreate(true); setConstructionFunction(&BareMetalDevice::create); -} - -IDevice::Ptr BareMetalDeviceFactory::create() const -{ - BareMetalDeviceConfigurationWizard wizard; - if (wizard.exec() != QDialog::Accepted) - return {}; - return wizard.device(); + setCanCreate(true); + setCreator([] { + BareMetalDeviceConfigurationWizard wizard; + if (wizard.exec() != QDialog::Accepted) + return IDevice::Ptr(); + return wizard.device(); + }); } } //namespace Internal diff --git a/src/plugins/baremetal/baremetaldevice.h b/src/plugins/baremetal/baremetaldevice.h index f10af5d4c5c..bfa3755885a 100644 --- a/src/plugins/baremetal/baremetaldevice.h +++ b/src/plugins/baremetal/baremetaldevice.h @@ -71,9 +71,7 @@ private: class BareMetalDeviceFactory final : public ProjectExplorer::IDeviceFactory { public: - explicit BareMetalDeviceFactory(); - - ProjectExplorer::IDevice::Ptr create() const final; + BareMetalDeviceFactory(); }; } //namespace Internal diff --git a/src/plugins/boot2qt/qdbdevice.cpp b/src/plugins/boot2qt/qdbdevice.cpp index 045ac410b65..e372c92b622 100644 --- a/src/plugins/boot2qt/qdbdevice.cpp +++ b/src/plugins/boot2qt/qdbdevice.cpp @@ -286,17 +286,14 @@ QdbLinuxDeviceFactory::QdbLinuxDeviceFactory() { setDisplayName(QdbDevice::tr("Boot2Qt Device")); setCombinedIcon(":/qdb/images/qdbdevicesmall.png", ":/qdb/images/qdbdevice.png"); - setCanCreate(true); setConstructionFunction(&QdbDevice::create); -} - -IDevice::Ptr QdbLinuxDeviceFactory::create() const -{ - QdbDeviceWizard wizard(Core::ICore::dialogParent()); - - if (wizard.exec() != QDialog::Accepted) - return IDevice::Ptr(); - return wizard.device(); + setCanCreate(true); + setCreator([] { + QdbDeviceWizard wizard(Core::ICore::dialogParent()); + if (wizard.exec() != QDialog::Accepted) + return IDevice::Ptr(); + return wizard.device(); + }); } } // namespace Internal diff --git a/src/plugins/boot2qt/qdbdevice.h b/src/plugins/boot2qt/qdbdevice.h index 30d66e4cec9..191a410633d 100644 --- a/src/plugins/boot2qt/qdbdevice.h +++ b/src/plugins/boot2qt/qdbdevice.h @@ -65,9 +65,6 @@ class QdbLinuxDeviceFactory final : public ProjectExplorer::IDeviceFactory { public: QdbLinuxDeviceFactory(); - -private: - ProjectExplorer::IDevice::Ptr create() const final; }; } // namespace Internal diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp index 26cbaf73e30..6c03d718055 100644 --- a/src/plugins/docker/dockerdevice.cpp +++ b/src/plugins/docker/dockerdevice.cpp @@ -1803,15 +1803,6 @@ QString DockerDevicePrivate::outputForRunInShell(const CommandLine &cmd) const // Factory -DockerDeviceFactory::DockerDeviceFactory() - : IDeviceFactory(Constants::DOCKER_DEVICE_TYPE) -{ - setDisplayName(DockerDevice::tr("Docker Device")); - setIcon(QIcon()); - setCanCreate(true); - setConstructionFunction([] { return DockerDevice::create({}); }); -} - class DockerImageItem final : public TreeItem, public DockerDeviceData { public: @@ -1915,7 +1906,7 @@ public: m_process->start(); } - DockerDevice::Ptr device() const + IDevice::Ptr device() const { const QModelIndexList selectedRows = m_view->selectionModel()->selectedRows(); QTC_ASSERT(selectedRows.size() == 1, return {}); @@ -1940,14 +1931,6 @@ public: QString m_selectedId; }; -IDevice::Ptr DockerDeviceFactory::create() const -{ - DockerDeviceSetupWizard wizard; - if (wizard.exec() != QDialog::Accepted) - return IDevice::Ptr(); - return wizard.device(); -} - void DockerDeviceWidget::updateDaemonStateTexts() { Utils::optional daemonState = DockerPlugin::isDaemonRunning(); @@ -1963,5 +1946,22 @@ void DockerDeviceWidget::updateDaemonStateTexts() } } +// Factory + +DockerDeviceFactory::DockerDeviceFactory() + : IDeviceFactory(Constants::DOCKER_DEVICE_TYPE) +{ + setDisplayName(DockerDevice::tr("Docker Device")); + setIcon(QIcon()); + setCanCreate(true); + setCreator([] { + DockerDeviceSetupWizard wizard; + if (wizard.exec() != QDialog::Accepted) + return IDevice::Ptr(); + return wizard.device(); + }); + setConstructionFunction([] { return DockerDevice::create({}); }); +} + } // Internal } // Docker diff --git a/src/plugins/docker/dockerdevice.h b/src/plugins/docker/dockerdevice.h index 1846c4f95f0..9ead0c5c102 100644 --- a/src/plugins/docker/dockerdevice.h +++ b/src/plugins/docker/dockerdevice.h @@ -157,8 +157,6 @@ class DockerDeviceFactory final : public ProjectExplorer::IDeviceFactory { public: DockerDeviceFactory(); - - ProjectExplorer::IDevice::Ptr create() const override; }; } // Internal diff --git a/src/plugins/mcusupport/mcusupportdevice.cpp b/src/plugins/mcusupport/mcusupportdevice.cpp index a6cb55e483c..7ff559ea70a 100644 --- a/src/plugins/mcusupport/mcusupportdevice.cpp +++ b/src/plugins/mcusupport/mcusupportdevice.cpp @@ -59,13 +59,9 @@ McuSupportDeviceFactory::McuSupportDeviceFactory() setDisplayName(McuSupportDevice::tr("MCU Device")); setCombinedIcon(":/mcusupport/images/mcusupportdevicesmall.png", ":/mcusupport/images/mcusupportdevice.png"); - setCanCreate(true); setConstructionFunction(&McuSupportDevice::create); -} - -ProjectExplorer::IDevice::Ptr McuSupportDeviceFactory::create() const -{ - return McuSupportDevice::create(); + setCanCreate(true); + setCreator(&McuSupportDevice::create); } } // namespace Internal diff --git a/src/plugins/mcusupport/mcusupportdevice.h b/src/plugins/mcusupport/mcusupportdevice.h index 8aff134753c..af8c79870f0 100644 --- a/src/plugins/mcusupport/mcusupportdevice.h +++ b/src/plugins/mcusupport/mcusupportdevice.h @@ -45,8 +45,6 @@ class McuSupportDeviceFactory final : public ProjectExplorer::IDeviceFactory { public: McuSupportDeviceFactory(); - - ProjectExplorer::IDevice::Ptr create() const override; }; } // namespace Internal diff --git a/src/plugins/projectexplorer/devicesupport/idevicefactory.cpp b/src/plugins/projectexplorer/devicesupport/idevicefactory.cpp index 675dcebd916..c286a97f9e3 100644 --- a/src/plugins/projectexplorer/devicesupport/idevicefactory.cpp +++ b/src/plugins/projectexplorer/devicesupport/idevicefactory.cpp @@ -81,6 +81,11 @@ bool IDeviceFactory::canCreate() const return m_canCreate; } +IDevice::Ptr IDeviceFactory::create() const +{ + return m_creator ? m_creator() : IDevice::Ptr(); +} + IDevice::Ptr IDeviceFactory::construct() const { return m_constructor ? m_constructor() : IDevice::Ptr(); @@ -119,6 +124,11 @@ void IDeviceFactory::setCanCreate(bool canCreate) m_canCreate = canCreate; } +void IDeviceFactory::setCreator(const std::function &creator) +{ + m_creator = creator; +} + void IDeviceFactory::setConstructionFunction(const std::function &constructor) { m_constructor = constructor; diff --git a/src/plugins/projectexplorer/devicesupport/idevicefactory.h b/src/plugins/projectexplorer/devicesupport/idevicefactory.h index 05bc2bf4934..2d44ebf162f 100644 --- a/src/plugins/projectexplorer/devicesupport/idevicefactory.h +++ b/src/plugins/projectexplorer/devicesupport/idevicefactory.h @@ -44,8 +44,7 @@ public: QIcon icon() const { return m_icon; } bool canCreate() const; IDevice::Ptr construct() const; - - virtual IDevice::Ptr create() const { return IDevice::Ptr(); } + IDevice::Ptr create() const; virtual bool canRestore(const QVariantMap &) const { return true; } @@ -61,8 +60,10 @@ protected: void setCombinedIcon(const Utils::FilePath &small, const Utils::FilePath &large); void setCanCreate(bool canCreate); void setConstructionFunction(const std::function &constructor); + void setCreator(const std::function &creator); private: + std::function m_creator; const Utils::Id m_deviceType; QString m_displayName; QIcon m_icon; diff --git a/src/plugins/qnx/qnxdevice.cpp b/src/plugins/qnx/qnxdevice.cpp index 24d9db7ad18..37d29516583 100644 --- a/src/plugins/qnx/qnxdevice.cpp +++ b/src/plugins/qnx/qnxdevice.cpp @@ -172,22 +172,19 @@ DeviceProcessSignalOperation::Ptr QnxDevice::signalOperation() const // Factory -QnxDeviceFactory::QnxDeviceFactory() - : ProjectExplorer::IDeviceFactory(Constants::QNX_QNX_OS_TYPE) +QnxDeviceFactory::QnxDeviceFactory() : IDeviceFactory(Constants::QNX_QNX_OS_TYPE) { setDisplayName(QnxDevice::tr("QNX Device")); setCombinedIcon(":/qnx/images/qnxdevicesmall.png", ":/qnx/images/qnxdevice.png"); - setCanCreate(true); setConstructionFunction(&QnxDevice::create); -} - -ProjectExplorer::IDevice::Ptr QnxDeviceFactory::create() const -{ - QnxDeviceWizard wizard; - if (wizard.exec() != QDialog::Accepted) - return ProjectExplorer::IDevice::Ptr(); - return wizard.device(); + setCanCreate(true); + setCreator([] { + QnxDeviceWizard wizard; + if (wizard.exec() != QDialog::Accepted) + return IDevice::Ptr(); + return wizard.device(); + }); } } // namespace Internal diff --git a/src/plugins/qnx/qnxdevice.h b/src/plugins/qnx/qnxdevice.h index 68ee45356e0..7ea275c7428 100644 --- a/src/plugins/qnx/qnxdevice.h +++ b/src/plugins/qnx/qnxdevice.h @@ -70,8 +70,6 @@ class QnxDeviceFactory final : public ProjectExplorer::IDeviceFactory { public: QnxDeviceFactory(); - - ProjectExplorer::IDevice::Ptr create() const override; }; } // namespace Internal diff --git a/src/plugins/remotelinux/filesystemaccess_test.cpp b/src/plugins/remotelinux/filesystemaccess_test.cpp index 603cd1b8782..9623b6f12d2 100644 --- a/src/plugins/remotelinux/filesystemaccess_test.cpp +++ b/src/plugins/remotelinux/filesystemaccess_test.cpp @@ -51,20 +51,18 @@ TestLinuxDeviceFactory::TestLinuxDeviceFactory() { setDisplayName("Generic Linux Device"); setIcon(QIcon()); - setCanCreate(true); setConstructionFunction(&LinuxDevice::create); -} - -IDevice::Ptr TestLinuxDeviceFactory::create() const -{ - LinuxDevice::Ptr newDev = LinuxDevice::create(); - qDebug() << "device : " << newDev->type(); - newDev->setType("test"); - QSsh::SshConnectionParameters sshParams = newDev->sshParameters(); - sshParams.setHost(TEST_IP); - sshParams.setPort(22); - newDev->setSshParameters(sshParams); - return newDev; + setCanCreate(true); + setCreator([] { + LinuxDevice::Ptr newDev = LinuxDevice::create(); + qDebug() << "device : " << newDev->type(); + newDev->setType("test"); + QSsh::SshConnectionParameters sshParams = newDev->sshParameters(); + sshParams.setHost(TEST_IP); + sshParams.setPort(22); + newDev->setSshParameters(sshParams); + return newDev; + }); } FilePath createFile(const QString &name) diff --git a/src/plugins/remotelinux/filesystemaccess_test.h b/src/plugins/remotelinux/filesystemaccess_test.h index b0c7a73f056..4b43e202d44 100644 --- a/src/plugins/remotelinux/filesystemaccess_test.h +++ b/src/plugins/remotelinux/filesystemaccess_test.h @@ -37,8 +37,6 @@ class TestLinuxDeviceFactory final : public ProjectExplorer::IDeviceFactory { public: TestLinuxDeviceFactory(); - - ProjectExplorer::IDevice::Ptr create() const override; }; class FileSystemAccessTest : public QObject diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp index 5422d8d9130..9387b46b7cd 100644 --- a/src/plugins/remotelinux/linuxdevice.cpp +++ b/src/plugins/remotelinux/linuxdevice.cpp @@ -754,17 +754,15 @@ LinuxDeviceFactory::LinuxDeviceFactory() { setDisplayName(LinuxDevice::tr("Generic Linux Device")); setIcon(QIcon()); - setCanCreate(true); setConstructionFunction(&LinuxDevice::create); + setCanCreate(true); + setCreator([] { + GenericLinuxDeviceConfigurationWizard wizard(Core::ICore::dialogParent()); + if (wizard.exec() != QDialog::Accepted) + return IDevice::Ptr(); + return wizard.device(); + }); } -IDevice::Ptr LinuxDeviceFactory::create() const -{ - GenericLinuxDeviceConfigurationWizard wizard(Core::ICore::dialogParent()); - if (wizard.exec() != QDialog::Accepted) - return IDevice::Ptr(); - return wizard.device(); -} - -} +} // namespace Internal } // namespace RemoteLinux diff --git a/src/plugins/remotelinux/linuxdevice.h b/src/plugins/remotelinux/linuxdevice.h index fa68624cacf..d2906b230c3 100644 --- a/src/plugins/remotelinux/linuxdevice.h +++ b/src/plugins/remotelinux/linuxdevice.h @@ -100,8 +100,6 @@ class LinuxDeviceFactory final : public ProjectExplorer::IDeviceFactory { public: LinuxDeviceFactory(); - - ProjectExplorer::IDevice::Ptr create() const override; }; } // namespace Internal diff --git a/src/plugins/webassembly/webassemblydevice.cpp b/src/plugins/webassembly/webassemblydevice.cpp index 753bd57f041..2e1eb31180d 100644 --- a/src/plugins/webassembly/webassemblydevice.cpp +++ b/src/plugins/webassembly/webassemblydevice.cpp @@ -47,10 +47,9 @@ WebAssemblyDevice::WebAssemblyDevice() setOsType(OsTypeOther); } -ProjectExplorer::IDevice::Ptr WebAssemblyDevice::create() +IDevice::Ptr WebAssemblyDevice::create() { - auto device = new WebAssemblyDevice; - return ProjectExplorer::IDevice::Ptr(device); + return IDevice::Ptr(new WebAssemblyDevice); } WebAssemblyDeviceFactory::WebAssemblyDeviceFactory() @@ -59,13 +58,9 @@ WebAssemblyDeviceFactory::WebAssemblyDeviceFactory() setDisplayName(WebAssemblyDevice::tr("WebAssembly Runtime")); setCombinedIcon(":/webassembly/images/webassemblydevicesmall.png", ":/webassembly/images/webassemblydevice.png"); - setCanCreate(true); setConstructionFunction(&WebAssemblyDevice::create); -} - -ProjectExplorer::IDevice::Ptr WebAssemblyDeviceFactory::create() const -{ - return WebAssemblyDevice::create(); + setCanCreate(true); + setCreator(&WebAssemblyDevice::create); } } // namespace Internal diff --git a/src/plugins/webassembly/webassemblydevice.h b/src/plugins/webassembly/webassemblydevice.h index 137a33aaef6..91382a05749 100644 --- a/src/plugins/webassembly/webassemblydevice.h +++ b/src/plugins/webassembly/webassemblydevice.h @@ -45,8 +45,6 @@ class WebAssemblyDeviceFactory final : public ProjectExplorer::IDeviceFactory { public: WebAssemblyDeviceFactory(); - - ProjectExplorer::IDevice::Ptr create() const override; }; } // namespace Internal From f2819878b13c3a5b82657a60920d806f58672599 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 26 Jan 2022 16:20:28 +0100 Subject: [PATCH 08/12] ProjectExplorer: Fix crash in toolchain dialog This amends 6cec0e2033, which did not take the bizarre code in the derived class into account. Change-Id: I508d483c8d38b2b99b3901ac0603c1bc016ee0ac Reviewed-by: Christian Stenger --- src/plugins/projectexplorer/gcctoolchain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index 5a83af5401e..061636cf427 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -1764,7 +1764,7 @@ ClangToolChainConfigWidget::ClangToolChainConfigWidget(ClangToolChain *tc) : return; // Remove m_abiWidget row because the parent toolchain abi is going to be used. - m_mainLayout->removeRow(m_mainLayout->rowCount() - 2); + m_mainLayout->removeRow(m_mainLayout->rowCount() - 3); // FIXME: Do something sane instead. m_abiWidget = nullptr; m_parentToolchainCombo = new QComboBox(this); From abbd6cdc8c0c31e647ff118ac6411a67e058dabf Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 26 Jan 2022 11:21:00 +0100 Subject: [PATCH 09/12] CMake: Use CommandLine to create the initial default parameters This has at least theoretically the potential to get quoting in "cross" configurations right. Since the consuming side is not ported, there should be no noticeable differences yet. Change-Id: I933ded4b1c9645055d3114d53f3d1b95b5c5539c Reviewed-by: Cristian Adam --- .../cmakebuildconfiguration.cpp | 82 +++++++++---------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index 32431563a17..6facbb8cab7 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -946,43 +946,45 @@ static bool isWindowsARM64(const Kit *k) && targetAbi.wordWidth() == 64; } -static QStringList defaultInitialCMakeArguments(const Kit *k, const QString buildType) +static CommandLine defaultInitialCMakeCommand(const Kit *k, const QString buildType) { // Generator: - QStringList initialArgs = CMakeGeneratorKitAspect::generatorArguments(k); + CMakeTool *tool = CMakeKitAspect::cmakeTool(k); + QTC_ASSERT(tool, return {}); + + CommandLine cmd{tool->cmakeExecutable()}; + cmd.addArgs(CMakeGeneratorKitAspect::generatorArguments(k)); // CMAKE_BUILD_TYPE: - if (!buildType.isEmpty() && !CMakeGeneratorKitAspect::isMultiConfigGenerator(k)) { - initialArgs.append(QString::fromLatin1("-DCMAKE_BUILD_TYPE:STRING=%1").arg(buildType)); - } + if (!buildType.isEmpty() && !CMakeGeneratorKitAspect::isMultiConfigGenerator(k)) + cmd.addArg("-DCMAKE_BUILD_TYPE:STRING=" + buildType); Internal::CMakeSpecificSettings *settings = Internal::CMakeProjectPlugin::projectTypeSpecificSettings(); // Package manager - if (!isDocker(k) && settings->packageManagerAutoSetup.value()) - initialArgs.append(QString::fromLatin1("-DCMAKE_PROJECT_INCLUDE_BEFORE:PATH=%1") - .arg("%{IDE:ResourcePath}/package-manager/auto-setup.cmake")); + if (!isDocker(k) && settings->packageManagerAutoSetup.value()) { + cmd.addArg("-DCMAKE_PROJECT_INCLUDE_BEFORE:PATH=" + "%{IDE:ResourcePath}/package-manager/auto-setup.cmake"); + } // Cross-compilation settings: if (!isIos(k)) { // iOS handles this differently const QString sysRoot = SysRootKitAspect::sysRoot(k).path(); if (!sysRoot.isEmpty()) { - initialArgs.append(QString::fromLatin1("-DCMAKE_SYSROOT:PATH=%1").arg(sysRoot)); + cmd.addArg("-DCMAKE_SYSROOT:PATH" + sysRoot); if (ToolChain *tc = ToolChainKitAspect::cxxToolChain(k)) { const QString targetTriple = tc->originalTargetTriple(); - initialArgs.append( - QString::fromLatin1("-DCMAKE_C_COMPILER_TARGET:STRING=%1").arg(targetTriple)); - initialArgs.append( - QString::fromLatin1("-DCMAKE_CXX_COMPILER_TARGET:STRING=%1").arg(targetTriple)); + cmd.addArg("-DCMAKE_C_COMPILER_TARGET:STRING=" + targetTriple); + cmd.addArg("-DCMAKE_CXX_COMPILER_TARGET:STRING=%1" + targetTriple); } } } - initialArgs += CMakeConfigurationKitAspect::toArgumentsList(k); - initialArgs += ProcessArgs::splitArgs(CMakeConfigurationKitAspect::additionalConfiguration(k)); + cmd.addArgs(CMakeConfigurationKitAspect::toArgumentsList(k)); + cmd.addArgs(CMakeConfigurationKitAspect::additionalConfiguration(k), CommandLine::Raw); - return initialArgs; + return cmd; } } // namespace Internal @@ -1067,19 +1069,19 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(Target *target, Id id) setInitializer([this, target](const BuildInfo &info) { const Kit *k = target->kit(); - QStringList initialArgs = defaultInitialCMakeArguments(k, info.typeName); + CommandLine cmd = defaultInitialCMakeCommand(k, info.typeName); setIsMultiConfig(CMakeGeneratorKitAspect::isMultiConfigGenerator(k)); // Android magic: if (DeviceTypeKitAspect::deviceTypeId(k) == Android::Constants::ANDROID_DEVICE_TYPE) { buildSteps()->appendStep(Android::Constants::ANDROID_BUILD_APK_ID); const auto &bs = buildSteps()->steps().constLast(); - initialArgs.append("-DANDROID_NATIVE_API_LEVEL:STRING=" + cmd.addArg("-DANDROID_NATIVE_API_LEVEL:STRING=" + bs->data(Android::Constants::AndroidNdkPlatform).toString()); auto ndkLocation = bs->data(Android::Constants::NdkLocation).value(); - initialArgs.append("-DANDROID_NDK:PATH=" + ndkLocation.path()); + cmd.addArg("-DANDROID_NDK:PATH=" + ndkLocation.path()); - initialArgs.append("-DCMAKE_TOOLCHAIN_FILE:PATH=" + cmd.addArg("-DCMAKE_TOOLCHAIN_FILE:PATH=" + ndkLocation.pathAppended("build/cmake/android.toolchain.cmake").path()); auto androidAbis = bs->data(Android::Constants::AndroidMkSpecAbis).toStringList(); @@ -1092,9 +1094,9 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(Target *target, Id id) } else { preferredAbi = androidAbis.first(); } - initialArgs.append("-DANDROID_ABI:STRING=" + preferredAbi); - initialArgs.append("-DANDROID_STL:STRING=c++_shared"); - initialArgs.append("-DCMAKE_FIND_ROOT_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}"); + cmd.addArg("-DANDROID_ABI:STRING=" + preferredAbi); + cmd.addArg("-DANDROID_STL:STRING=c++_shared"); + cmd.addArg("-DCMAKE_FIND_ROOT_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}"); QtSupport::QtVersion *qt = QtSupport::QtKitAspect::qtVersion(k); auto sdkLocation = bs->data(Android::Constants::SdkLocation).value(); @@ -1102,11 +1104,11 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(Target *target, Id id) if (qt && qt->qtVersion() >= QtSupport::QtVersionNumber{6, 0, 0}) { // Don't build apk under ALL target because Qt Creator will handle it if (qt->qtVersion() >= QtSupport::QtVersionNumber{6, 1, 0}) - initialArgs.append("-DQT_NO_GLOBAL_APK_TARGET_PART_OF_ALL:BOOL=ON"); - initialArgs.append("-DQT_HOST_PATH:PATH=%{Qt:QT_HOST_PREFIX}"); - initialArgs.append("-DANDROID_SDK_ROOT:PATH=" + sdkLocation.path()); + cmd.addArg("-DQT_NO_GLOBAL_APK_TARGET_PART_OF_ALL:BOOL=ON"); + cmd.addArg("-DQT_HOST_PATH:PATH=%{Qt:QT_HOST_PREFIX}"); + cmd.addArg("-DANDROID_SDK_ROOT:PATH=" + sdkLocation.path()); } else { - initialArgs.append("-DANDROID_SDK:PATH=" + sdkLocation.path()); + cmd.addArg("-DANDROID_SDK:PATH=" + sdkLocation.path()); } } @@ -1127,20 +1129,20 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(Target *target, Id id) const QString sysroot = deviceType == Ios::Constants::IOS_DEVICE_TYPE ? QLatin1String("iphoneos") : QLatin1String("iphonesimulator"); - initialArgs.append(CMAKE_QT6_TOOLCHAIN_FILE_ARG); - initialArgs.append("-DCMAKE_OSX_ARCHITECTURES:STRING=" + architecture); - initialArgs.append("-DCMAKE_OSX_SYSROOT:STRING=" + sysroot); - initialArgs.append("%{" + QLatin1String(DEVELOPMENT_TEAM_FLAG) + "}"); - initialArgs.append("%{" + QLatin1String(PROVISIONING_PROFILE_FLAG) + "}"); + cmd.addArg(CMAKE_QT6_TOOLCHAIN_FILE_ARG); + cmd.addArg("-DCMAKE_OSX_ARCHITECTURES:STRING=" + architecture); + cmd.addArg("-DCMAKE_OSX_SYSROOT:STRING=" + sysroot); + cmd.addArg("%{" + QLatin1String(DEVELOPMENT_TEAM_FLAG) + "}"); + cmd.addArg("%{" + QLatin1String(PROVISIONING_PROFILE_FLAG) + "}"); } } else if (device && device->osType() == Utils::OsTypeMac) { - initialArgs.append("%{" + QLatin1String(CMAKE_OSX_ARCHITECTURES_FLAG) + "}"); + cmd.addArg("%{" + QLatin1String(CMAKE_OSX_ARCHITECTURES_FLAG) + "}"); } if (isWebAssembly(k) || isQnx(k) || isWindowsARM64(k)) { const QtSupport::QtVersion *qt = QtSupport::QtKitAspect::qtVersion(k); if (qt && qt->qtVersion().majorVersion >= 6) - initialArgs.append(CMAKE_QT6_TOOLCHAIN_FILE_ARG); + cmd.addArg(CMAKE_QT6_TOOLCHAIN_FILE_ARG); } if (info.buildDirectory.isEmpty()) { @@ -1155,7 +1157,7 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(Target *target, Id id) info.extraInfo.value().value(Constants::CMAKE_HOME_DIR))); } - setInitialCMakeArguments(initialArgs); + setInitialCMakeArguments(cmd.splitArguments()); setCMakeBuildType(info.typeName); }); @@ -1200,12 +1202,10 @@ bool CMakeBuildConfiguration::fromMap(const QVariantMap &map) } }(); if (initialCMakeArguments().isEmpty()) { - QStringList initialArgs = defaultInitialCMakeArguments(kit(), buildTypeName) - + Utils::transform(conf.toList(), [this](const CMakeConfigItem &i) { - return i.toArgument(macroExpander()); - }); - - setInitialCMakeArguments(initialArgs); + CommandLine cmd = defaultInitialCMakeCommand(kit(), buildTypeName); + for (const CMakeConfigItem &item : conf) + cmd.addArg(item.toArgument(macroExpander())); + setInitialCMakeArguments(cmd.splitArguments()); } return true; From c492b29a45aefc05336ce8d53f1a49e233f4ac39 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 26 Jan 2022 11:52:07 +0100 Subject: [PATCH 10/12] Nanotrace: Make nanotrace commonly usable CMake's auto symbol export is a plain hack and does not work for other build systems. Besides fixing some non-working implicit conversions when using Qt5.15. Change-Id: I80b77a4ebf8cad30c78c1c2ef2034e62d2063399 Reviewed-by: Christian Kandeler Reviewed-by: Reviewed-by: Christian Stenger --- .../instances/nodeinstanceclientproxy.cpp | 8 +++---- src/libs/nanotrace/CMakeLists.txt | 1 - src/libs/nanotrace/nanotrace.h | 21 +++++++++++++------ src/libs/nanotrace/nanotrace.qbs | 1 - .../instances/baseconnectionmanager.cpp | 4 ++-- .../instances/nodeinstanceserverproxy.cpp | 4 ++-- 6 files changed, 23 insertions(+), 16 deletions(-) diff --git a/share/qtcreator/qml/qmlpuppet/instances/nodeinstanceclientproxy.cpp b/share/qtcreator/qml/qmlpuppet/instances/nodeinstanceclientproxy.cpp index ae236266249..c1ca741e179 100644 --- a/share/qtcreator/qml/qmlpuppet/instances/nodeinstanceclientproxy.cpp +++ b/share/qtcreator/qml/qmlpuppet/instances/nodeinstanceclientproxy.cpp @@ -206,12 +206,12 @@ void NodeInstanceClientProxy::writeCommand(const QVariant &command) SyncNanotraceCommand cmd = command.value(); NANOTRACE_INSTANT_ARGS("Sync", "writeCommand", {"name", cmd.name().toStdString()}, - {"counter", m_writeCommandCounter}); + {"counter", int64_t(m_writeCommandCounter)}); } else { NANOTRACE_INSTANT_ARGS("Update", "writeCommand", {"name", command.typeName()}, - {"counter", m_writeCommandCounter}); + {"counter", int64_t(m_writeCommandCounter)}); } } #endif @@ -409,14 +409,14 @@ void NodeInstanceClientProxy::readDataStream() SyncNanotraceCommand cmd = command.value(); NANOTRACE_INSTANT_ARGS("Sync", "readCommand", {"name", cmd.name().toStdString()}, - {"counter", readCommandCounter}); + {"counter", int64_t(readCommandCounter)}); // Do not dispatch this command. continue; } else { NANOTRACE_INSTANT_ARGS("Update", "readCommand", {"name", command.typeName()}, - {"counter", readCommandCounter}); + {"counter", int64_t(readCommandCounter)}); } } #endif diff --git a/src/libs/nanotrace/CMakeLists.txt b/src/libs/nanotrace/CMakeLists.txt index 053d7b1c487..6435063046f 100644 --- a/src/libs/nanotrace/CMakeLists.txt +++ b/src/libs/nanotrace/CMakeLists.txt @@ -7,6 +7,5 @@ add_qtc_library(Nanotrace PROPERTIES CXX_VISIBILITY_PRESET default VISIBILITY_INLINES_HIDDEN OFF - WINDOWS_EXPORT_ALL_SYMBOLS ON ) diff --git a/src/libs/nanotrace/nanotrace.h b/src/libs/nanotrace/nanotrace.h index c90407d6365..0df2be76df1 100644 --- a/src/libs/nanotrace/nanotrace.h +++ b/src/libs/nanotrace/nanotrace.h @@ -25,6 +25,15 @@ #pragma once +#include + +#if defined(NANOTRACE_LIBRARY) +# define NANOTRACESHARED_EXPORT Q_DECL_EXPORT +#else +# define NANOTRACESHARED_EXPORT Q_DECL_IMPORT +#endif + + #include #include #include @@ -68,7 +77,7 @@ using Units = std::chrono::nanoseconds; using Clock = std::chrono::high_resolution_clock; using TimePoint = std::chrono::time_point< Clock >; -class Arg +class NANOTRACESHARED_EXPORT Arg { public: using SupportedType = std::variant; @@ -82,19 +91,19 @@ private: SupportedType m_value; }; -void init(const std::string &process, const std::string &thread, const std::string &path); +NANOTRACESHARED_EXPORT void init(const std::string &process, const std::string &thread, const std::string &path); -void shutdown(); +NANOTRACESHARED_EXPORT void shutdown(); -void flush(); +NANOTRACESHARED_EXPORT void flush(); -void addTracePoint( +NANOTRACESHARED_EXPORT void addTracePoint( const std::string &name, const std::string &cat, char phase, std::initializer_list< Nanotrace::Arg > arguments); -class ScopeTracer +class NANOTRACESHARED_EXPORT ScopeTracer { public: ScopeTracer( diff --git a/src/libs/nanotrace/nanotrace.qbs b/src/libs/nanotrace/nanotrace.qbs index 388bfb20f87..0e0c9237dd7 100644 --- a/src/libs/nanotrace/nanotrace.qbs +++ b/src/libs/nanotrace/nanotrace.qbs @@ -2,7 +2,6 @@ QtcLibrary { name: "Nanotrace" cpp.defines: base.concat("NANOTRACE_LIBRARY", "NANOTRACE_ENABLED") - cpp.visibility: "default" files: [ "nanotrace.cpp", diff --git a/src/plugins/qmldesigner/designercore/instances/baseconnectionmanager.cpp b/src/plugins/qmldesigner/designercore/instances/baseconnectionmanager.cpp index 72552fdb7ae..2c9408bf424 100644 --- a/src/plugins/qmldesigner/designercore/instances/baseconnectionmanager.cpp +++ b/src/plugins/qmldesigner/designercore/instances/baseconnectionmanager.cpp @@ -134,7 +134,7 @@ void BaseConnectionManager::readDataStream(Connection &connection) SyncNanotraceCommand cmd = command.value(); NANOTRACE_INSTANT_ARGS("Sync", "readCommand", {"name", cmd.name().toStdString()}, - {"counter", commandCounter}); + {"counter", int64_t(commandCounter)}); writeCommand(command); // Do not dispatch this command. @@ -143,7 +143,7 @@ void BaseConnectionManager::readDataStream(Connection &connection) } else { NANOTRACE_INSTANT_ARGS("Update", "readCommand", {"name", command.typeName()}, - {"counter", commandCounter}); + {"counter", int64_t(commandCounter)}); } } #endif diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp index 4f09eb7cf1a..01ed33ea495 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp @@ -196,12 +196,12 @@ void NodeInstanceServerProxy::writeCommand(const QVariant &command) SyncNanotraceCommand cmd = command.value(); NANOTRACE_INSTANT_ARGS("Sync", "writeCommand", {"name", cmd.name().toStdString()}, - {"counter", m_connectionManager.writeCounter()}); + {"counter", int64_t(m_connectionManager.writeCounter())}); } else { NANOTRACE_INSTANT_ARGS("Update", "writeCommand", {"name", command.typeName()}, - {"counter", m_connectionManager.writeCounter()}); + {"counter", int64_t(m_connectionManager.writeCounter())}); } #endif From f9de2f2b23923201e3443c63b2ebe33b41ab0eb1 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Wed, 26 Jan 2022 16:34:57 +0100 Subject: [PATCH 11/12] Qt Creator plugin wizard: Bump checkout github action to v2 v1 has security concerns Change-Id: Ia88cf55197a64af819abe07bdac698a29bec8aeb Reviewed-by: Cristian Adam Reviewed-by: --- .../wizards/qtcreatorplugin/github_workflows_build_cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/qtcreator/templates/wizards/qtcreatorplugin/github_workflows_build_cmake.yml b/share/qtcreator/templates/wizards/qtcreatorplugin/github_workflows_build_cmake.yml index b50b67e9250..53c6152ee8b 100644 --- a/share/qtcreator/templates/wizards/qtcreatorplugin/github_workflows_build_cmake.yml +++ b/share/qtcreator/templates/wizards/qtcreatorplugin/github_workflows_build_cmake.yml @@ -35,7 +35,7 @@ jobs: } steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Download Ninja and CMake shell: cmake -P {0} From 181e74ebc3582a516a7957774488291d08a4cc5e Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 27 Jan 2022 09:16:02 +0100 Subject: [PATCH 12/12] Docker: Fix iterateWithFind() Amends 22dd26bc76d. Change-Id: I0be8d8236795a9e93ab93f89df56fd14e378e6e6 Reviewed-by: hjk --- src/plugins/docker/dockerdevice.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp index 6c03d718055..1f6744d3894 100644 --- a/src/plugins/docker/dockerdevice.cpp +++ b/src/plugins/docker/dockerdevice.cpp @@ -1522,7 +1522,8 @@ void DockerDevice::iterateWithFind(const FilePath &filePath, continue; const FilePath fp = FilePath::fromString(entry); - if (!Utils::anyOf(criticalWildcards, + if (!criticalWildcards.isEmpty() && + !Utils::anyOf(criticalWildcards, [name = fp.fileName()](const QString &pattern) { const QRegularExpression regex(QRegularExpression::wildcardToRegularExpression(pattern)); if (regex.match(name).hasMatch())