diff --git a/src/libs/utils/abstractprocess.h b/src/libs/utils/abstractprocess.h index 28a8a59e06c47958eb7c5c9426bdc87d8ac7cba7..49564e4fd043462e8ba57f4a612c0b10c2e0b093 100644 --- a/src/libs/utils/abstractprocess.h +++ b/src/libs/utils/abstractprocess.h @@ -32,6 +32,8 @@ #include "utils_global.h" +#include "environment.h" + #include <QtCore/QStringList> namespace Utils { @@ -45,10 +47,10 @@ public: QString workingDirectory() const { return m_workingDir; } void setWorkingDirectory(const QString &dir) { m_workingDir = dir; } - QStringList environment() const { return m_environment; } - void setEnvironment(const QStringList &env) { m_environment = env; } + void setEnvironment(const Environment &env) { m_environment = env; } + Environment environment() const { return m_environment; } - virtual bool start(const QString &program, const QStringList &args) = 0; + virtual bool start(const QString &program, const QString &args) = 0; virtual void stop() = 0; virtual bool isRunning() const = 0; @@ -63,14 +65,15 @@ public: static QStringList fixWinEnvironment(const QStringList &env); // Quote a Windows command line correctly for the "CreateProcess" API static QString createWinCommandline(const QString &program, const QStringList &args); + static QString createWinCommandline(const QString &program, const QString &args); // Create a bytearray suitable to be passed on as environment // to the "CreateProcess" API (0-terminated UTF 16 strings). static QByteArray createWinEnvironment(const QStringList &env); #endif -private: +protected: QString m_workingDir; - QStringList m_environment; + Environment m_environment; }; } //namespace Utils diff --git a/src/libs/utils/abstractprocess_win.cpp b/src/libs/utils/abstractprocess_win.cpp index be99c70bf00ab1f017440cab3f5eb6de97ed76e3..8c63b5e403e2f4ae33d2d97c27708f503a777fc7 100644 --- a/src/libs/utils/abstractprocess_win.cpp +++ b/src/libs/utils/abstractprocess_win.cpp @@ -51,49 +51,57 @@ QStringList AbstractProcess::fixWinEnvironment(const QStringList &env) return envStrings; } -QString AbstractProcess::createWinCommandline(const QString &program, const QStringList &args) +static QString quoteWinCommand(const QString &program) { const QChar doubleQuote = QLatin1Char('"'); - const QChar blank = QLatin1Char(' '); - const QChar backSlash = QLatin1Char('\\'); + // add the programm as the first arg ... it works better QString programName = program; - if (!programName.startsWith(doubleQuote) && !programName.endsWith(doubleQuote) && programName.contains(blank)) { - programName.insert(0, doubleQuote); + programName.replace(QLatin1Char('/'), QLatin1Char('\\')); + if (!programName.startsWith(doubleQuote) && !programName.endsWith(doubleQuote) + && programName.contains(QLatin1Char(' '))) { + programName.prepend(doubleQuote); programName.append(doubleQuote); } - // add the prgram as the first arrg ... it works better - programName.replace(QLatin1Char('/'), backSlash); - QString cmdLine = programName; - if (args.empty()) - return cmdLine; + return programName; +} + +static QString quoteWinArgument(const QString &arg) +{ + if (!arg.length()) + return QString::fromLatin1("\"\""); + + QString ret(arg); + // Quotes are escaped and their preceding backslashes are doubled. + ret.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\\1\\1\\\"")); + if (ret.contains(QRegExp(QLatin1String("\\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\" + ret.replace(QRegExp(QLatin1String("(\\\\*)$")), QLatin1String("\"\\1")); + ret.prepend(QLatin1Char('"')); + } + return ret; +} - cmdLine += blank; - for (int i = 0; i < args.size(); ++i) { - QString tmp = args.at(i); - // in the case of \" already being in the string the \ must also be escaped - tmp.replace(QLatin1String("\\\""), QLatin1String("\\\\\"")); - // escape a single " because the arguments will be parsed - tmp.replace(QString(doubleQuote), QLatin1String("\\\"")); - if (tmp.isEmpty() || tmp.contains(blank) || tmp.contains('\t')) { - // 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\" - QString endQuote(doubleQuote); - int i = tmp.length(); - while (i > 0 && tmp.at(i - 1) == backSlash) { - --i; - endQuote += backSlash; - } - cmdLine += QLatin1String(" \""); - cmdLine += tmp.left(i); - cmdLine += endQuote; - } else { - cmdLine += blank; - cmdLine += tmp; - } +QString AbstractProcess::createWinCommandline(const QString &program, const QStringList &args) +{ + QString programName = quoteWinCommand(program); + foreach (const QString &arg, args) { + programName += QLatin1Char(' '); + programName += quoteWinArgument(arg); + } + return programName; +} + +QString AbstractProcess::createWinCommandline(const QString &program, const QString &args) +{ + QString programName = quoteWinCommand(program); + if (!args.isEmpty()) { + programName += QLatin1Char(' '); + programName += args; } - return cmdLine; + return programName; } QByteArray AbstractProcess::createWinEnvironment(const QStringList &env) diff --git a/src/libs/utils/consoleprocess.h b/src/libs/utils/consoleprocess.h index ced9aa352ecaea68e6803b9b964f5bc968dc0d59..a64132e586673ebe6a65b7c7cf6a21d2b2547f00 100644 --- a/src/libs/utils/consoleprocess.h +++ b/src/libs/utils/consoleprocess.h @@ -54,7 +54,7 @@ public: ConsoleProcess(QObject *parent = 0); ~ConsoleProcess(); - bool start(const QString &program, const QStringList &args); + bool start(const QString &program, const QString &args); void stop(); void setMode(Mode m); diff --git a/src/libs/utils/consoleprocess_unix.cpp b/src/libs/utils/consoleprocess_unix.cpp index 32528d44af018e9a4fb96b334c7979630b4330fe..6a3d8e8a9be63845c5cb5ae2f3dc69a01beb52a2 100644 --- a/src/libs/utils/consoleprocess_unix.cpp +++ b/src/libs/utils/consoleprocess_unix.cpp @@ -29,6 +29,9 @@ #include "consoleprocess.h" +#include "environment.h" +#include "qtcprocess.h" + #include <QtCore/QCoreApplication> #include <QtCore/QDir> #include <QtCore/QSettings> @@ -66,6 +69,7 @@ ConsoleProcessPrivate::ConsoleProcessPrivate() : m_mode(ConsoleProcess::Run), m_appPid(0), m_stubSocket(0), + m_tempFile(0), m_settings(0) { } @@ -114,18 +118,49 @@ void ConsoleProcess::setSettings(QSettings *settings) d->m_settings = settings; } -bool ConsoleProcess::start(const QString &program, const QStringList &args) +bool ConsoleProcess::start(const QString &program, const QString &args) { if (isRunning()) return false; + QtcProcess::SplitError perr; + QStringList pargs = QtcProcess::prepareArgs(args, &perr, &m_environment, &m_workingDir); + QString pcmd; + if (perr == QtcProcess::SplitOk) { + pcmd = program; + } else { + if (perr != QtcProcess::FoundMeta) { + emit processMessage(tr("Quoting error in command."), true); + return false; + } + if (d->m_mode == Debug) { + // FIXME: QTCREATORBUG-2809 + emit processMessage(tr("Debugging complex shell commands in a terminal" + " is currently not supported."), true); + return false; + } + pcmd = QLatin1String("/bin/sh"); + pargs << QLatin1String("-c") << (QtcProcess::quoteArg(program) + QLatin1Char(' ') + args); + } + + QtcProcess::SplitError qerr; + QStringList xtermArgs = QtcProcess::prepareArgs(terminalEmulator(d->m_settings), &qerr, + &m_environment, &m_workingDir); + if (qerr != QtcProcess::SplitOk) { + emit processMessage(qerr == QtcProcess::BadQuoting + ? tr("Quoting error in terminal command.") + : tr("Terminal command may not be a shell command."), true); + return false; + } + const QString err = stubServerListen(); if (!err.isEmpty()) { emit processMessage(msgCommChannelFailed(err), true); return false; } - if (!environment().isEmpty()) { + QStringList env = m_environment.toStringList(); + if (!env.isEmpty()) { d->m_tempFile = new QTemporaryFile(); if (!d->m_tempFile->open()) { stubServerShutdown(); @@ -134,14 +169,13 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args) d->m_tempFile = 0; return false; } - foreach (const QString &var, environment()) { + foreach (const QString &var, env) { d->m_tempFile->write(var.toLocal8Bit()); d->m_tempFile->write("", 1); } d->m_tempFile->flush(); } - QStringList xtermArgs = terminalEmulator(d->m_settings).split(QLatin1Char(' ')); // FIXME: quoting xtermArgs #ifdef Q_OS_MAC << (QCoreApplication::applicationDirPath() + QLatin1String("/../Resources/qtcreator_process_stub")) @@ -153,7 +187,7 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args) << msgPromptToClose() << workingDirectory() << (d->m_tempFile ? d->m_tempFile->fileName() : QString()) - << program << args; + << pcmd << pargs; QString xterm = xtermArgs.takeFirst(); d->m_process.start(xterm, xtermArgs); diff --git a/src/libs/utils/consoleprocess_win.cpp b/src/libs/utils/consoleprocess_win.cpp index eeaa33360457b2940635a3370df5449d634e00a1..d93175f63750c2b717feeecf863cb1dad127ac3a 100644 --- a/src/libs/utils/consoleprocess_win.cpp +++ b/src/libs/utils/consoleprocess_win.cpp @@ -28,6 +28,8 @@ **************************************************************************/ #include "consoleprocess.h" +#include "environment.h" +#include "qtcprocess.h" #include "winutils.h" #include <windows.h> @@ -115,18 +117,28 @@ QProcess::ExitStatus ConsoleProcess::exitStatus() const return d->m_appStatus; } -bool ConsoleProcess::start(const QString &program, const QStringList &args) +bool ConsoleProcess::start(const QString &program, const QString &args) { if (isRunning()) return false; + QString pcmd; + QString pargs; + if (d->m_mode != Run) { // The debugger engines already pre-process the arguments. + pcmd = program; + pargs = args; + } else { + QtcProcess::prepareCommand(program, args, &pcmd, &pargs, &m_environment, &m_workingDir); + } + const QString err = stubServerListen(); if (!err.isEmpty()) { emit processMessage(msgCommChannelFailed(err), true); return false; } - if (!environment().isEmpty()) { + QStringList env = m_environment.toStringList(); + if (!env.isEmpty()) { d->m_tempFile = new QTemporaryFile(); if (!d->m_tempFile->open()) { stubServerShutdown(); @@ -138,7 +150,7 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args) QTextStream out(d->m_tempFile); out.setCodec("UTF-16LE"); out.setGenerateByteOrderMark(false); - foreach (const QString &var, fixWinEnvironment(environment())) + foreach (const QString &var, fixWinEnvironment(env)) out << var << QChar(0); out << QChar(0); } @@ -159,7 +171,7 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args) << d->m_stubServer.fullServerName() << workDir << (d->m_tempFile ? d->m_tempFile->fileName() : 0) - << createWinCommandline(program, args) + << createWinCommandline(pcmd, pargs) << msgPromptToClose(); const QString cmdLine = createWinCommandline( diff --git a/src/libs/utils/environment.cpp b/src/libs/utils/environment.cpp index 03b73435920ee15ee5f2a768a4517c37513f11cd..34a8fa3abae7ab818dc2ad9e3a282deac996aa26 100644 --- a/src/libs/utils/environment.cpp +++ b/src/libs/utils/environment.cpp @@ -332,62 +332,6 @@ bool Environment::operator==(const Environment &other) const return m_values == other.m_values; } -QStringList Environment::parseCombinedArgString(const QString &program) -{ - QStringList args; - QString tmp; - int quoteCount = 0; - bool inQuote = false; - - // handle quoting. tokens can be surrounded by double quotes - // "hello world". three consecutive double quotes represent - // the quote character itself. - for (int i = 0; i < program.size(); ++i) { - if (program.at(i) == QLatin1Char('"')) { - ++quoteCount; - if (quoteCount == 3) { - // third consecutive quote - quoteCount = 0; - tmp += program.at(i); - } - continue; - } - if (quoteCount) { - if (quoteCount == 1) - inQuote = !inQuote; - quoteCount = 0; - } - if (!inQuote && program.at(i).isSpace()) { - if (!tmp.isEmpty()) { - args += tmp; - tmp.clear(); - } - } else { - tmp += program.at(i); - } - } - if (!tmp.isEmpty()) - args += tmp; - return args; -} - -QString Environment::joinArgumentList(const QStringList &arguments) -{ - QString result; - const QChar doubleQuote = QLatin1Char('"'); - foreach (QString arg, arguments) { - if (!result.isEmpty()) - result += QLatin1Char(' '); - arg.replace(QString(doubleQuote), QLatin1String("\"\"\"")); - if (arg.contains(QLatin1Char(' '))) { - arg.insert(0, doubleQuote); - arg += doubleQuote; - } - result += arg; - } - return result; -} - /** Expand environment variables in a string. * * Environment variables are accepted in the following forms: diff --git a/src/libs/utils/environment.h b/src/libs/utils/environment.h index 5e505656d02e59193443eb8656cadb1aee41cc87..fe2ddc701d39482b3ef07612676bfe2d8766d1c8 100644 --- a/src/libs/utils/environment.h +++ b/src/libs/utils/environment.h @@ -94,9 +94,6 @@ public: const QStringList & additionalDirs = QStringList()) const; QStringList path() const; - static QStringList parseCombinedArgString(const QString &program); - static QString joinArgumentList(const QStringList &arguments); - QString expandVariables(const QString &) const; QStringList expandVariables(const QStringList &) const; diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index a7ed541148934cbd45b5411975db7a2c9cd7e182..0ae0833f572dffded5cf411f56a962f81c607bc8 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -243,7 +243,7 @@ CMakeBuildConfiguration *CMakeBuildConfigurationFactory::create(ProjectExplorer: MakeStep *cleanMakeStep = new MakeStep(cleanSteps); cleanSteps->insertStep(0, cleanMakeStep); - cleanMakeStep->setAdditionalArguments(QStringList() << "clean"); + cleanMakeStep->setAdditionalArguments("clean"); cleanMakeStep->setClean(true); CMakeOpenProjectWizard copw(cmtarget->cmakeProject()->projectManager(), diff --git a/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp b/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp index 56870530fbff05b96d1bb30717bac4526b2ff8d1..6b1c4ba7135d1409c0612fab4498541e103273bd 100644 --- a/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp @@ -202,12 +202,12 @@ void CMakeOpenProjectWizard::setMsvcVersion(const QString &version) m_msvcVersion = version; } -QStringList CMakeOpenProjectWizard::arguments() const +QString CMakeOpenProjectWizard::arguments() const { return m_arguments; } -void CMakeOpenProjectWizard::setArguments(const QStringList &args) +void CMakeOpenProjectWizard::setArguments(const QString &args) { m_arguments = args; } @@ -426,7 +426,6 @@ void CMakeRunPage::runCMake() { m_runCMake->setEnabled(false); m_argumentsLineEdit->setEnabled(false); - QStringList arguments = Utils::Environment::parseCombinedArgString(m_argumentsLineEdit->text()); CMakeManager *cmakeManager = m_cmakeWizard->cmakeManager(); #ifdef Q_OS_WIN @@ -464,11 +463,11 @@ void CMakeRunPage::runCMake() m_output->clear(); if (m_cmakeWizard->cmakeManager()->isCMakeExecutableValid()) { - m_cmakeProcess = new QProcess(); + m_cmakeProcess = new Utils::QtcProcess(); connect(m_cmakeProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(cmakeReadyReadStandardOutput())); connect(m_cmakeProcess, SIGNAL(readyReadStandardError()), this, SLOT(cmakeReadyReadStandardError())); connect(m_cmakeProcess, SIGNAL(finished(int)), this, SLOT(cmakeFinished())); - cmakeManager->createXmlFile(m_cmakeProcess, arguments, m_cmakeWizard->sourceDirectory(), m_buildDirectory, env, generator); + cmakeManager->createXmlFile(m_cmakeProcess, m_argumentsLineEdit->text(), m_cmakeWizard->sourceDirectory(), m_buildDirectory, env, generator); } else { m_runCMake->setEnabled(true); m_argumentsLineEdit->setEnabled(true); @@ -522,7 +521,7 @@ void CMakeRunPage::cmakeFinished() } m_cmakeProcess->deleteLater(); m_cmakeProcess = 0; - m_cmakeWizard->setArguments(Utils::Environment::parseCombinedArgString(m_argumentsLineEdit->text())); + m_cmakeWizard->setArguments(m_argumentsLineEdit->text()); //TODO Actually test that running cmake was finished, for setting this bool emit completeChanged(); } diff --git a/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.h b/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.h index d38edd6b4be4fb269b37b94b3763ce1445ea6081..d28b77a9a0a60b9c36508d28e164d81514b2a93b 100644 --- a/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.h +++ b/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.h @@ -32,8 +32,8 @@ #include <utils/environment.h> #include <utils/wizard.h> +#include <utils/qtcprocess.h> -#include <QtCore/QProcess> #include <QtGui/QPushButton> #include <QtGui/QComboBox> #include <QtGui/QLineEdit> @@ -81,8 +81,8 @@ public: QString sourceDirectory() const; void setBuildDirectory(const QString &directory); CMakeManager *cmakeManager() const; - QStringList arguments() const; - void setArguments(const QStringList &args); + QString arguments() const; + void setArguments(const QString &args); Utils::Environment environment() const; QString msvcVersion() const; void setMsvcVersion(const QString &version); @@ -93,7 +93,7 @@ private: CMakeManager *m_cmakeManager; QString m_buildDirectory; QString m_sourceDirectory; - QStringList m_arguments; + QString m_arguments; QString m_msvcVersion; bool m_creatingCbpFiles; Utils::Environment m_environment; @@ -140,7 +140,7 @@ private: CMakeOpenProjectWizard *m_cmakeWizard; QPlainTextEdit *m_output; QPushButton *m_runCMake; - QProcess *m_cmakeProcess; + Utils::QtcProcess *m_cmakeProcess; QLineEdit *m_argumentsLineEdit; Utils::PathChooser *m_cmakeExecutable; QComboBox *m_generatorComboBox; diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp index 2403846cd9ccfc7fd7433722c3864ffb75b4e4b3..200d4037ceed0217c9624b770e76598d8c00a659 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp @@ -32,6 +32,7 @@ #include "cmakeproject.h" #include <utils/synchronousprocess.h> +#include <utils/qtcprocess.h> #include <coreplugin/icore.h> #include <coreplugin/uniqueidmanager.h> @@ -102,7 +103,7 @@ bool CMakeManager::hasCodeBlocksMsvcGenerator() const // we probably want the process instead of this function // cmakeproject then could even run the cmake process in the background, adding the files afterwards // sounds like a plan -void CMakeManager::createXmlFile(QProcess *proc, const QStringList &arguments, +void CMakeManager::createXmlFile(Utils::QtcProcess *proc, const QString &arguments, const QString &sourceDirectory, const QDir &buildDirectory, const Utils::Environment &env, const QString &generator) { @@ -117,11 +118,16 @@ void CMakeManager::createXmlFile(QProcess *proc, const QStringList &arguments, QString buildDirectoryPath = buildDirectory.absolutePath(); buildDirectory.mkpath(buildDirectoryPath); proc->setWorkingDirectory(buildDirectoryPath); - proc->setEnvironment(env.toStringList()); + proc->setEnvironment(env); const QString srcdir = buildDirectory.exists(QLatin1String("CMakeCache.txt")) ? QString(QLatin1Char('.')) : sourceDirectory; - proc->start(cmakeExecutable(), QStringList() << srcdir << arguments << generator); + QString args; + Utils::QtcProcess::addArg(&args, srcdir); + Utils::QtcProcess::addArgs(&args, arguments); + Utils::QtcProcess::addArg(&args, generator); + proc->setCommand(cmakeExecutable(), args); + proc->start(); } QString CMakeManager::findCbpFile(const QDir &directory) diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h index 9da4e120cc4fca6452aeba1a51106004b53cbafa..44ecd271cdfaeb388168a3527670bf7e9bafa6df 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h @@ -44,6 +44,10 @@ QT_FORWARD_DECLARE_CLASS(QProcess) QT_FORWARD_DECLARE_CLASS(QLabel) +namespace Utils { +class QtcProcess; +} + namespace CMakeProjectManager { namespace Internal { @@ -66,8 +70,8 @@ public: void setCMakeExecutable(const QString &executable); - void createXmlFile(QProcess *process, - const QStringList &arguments, + void createXmlFile(Utils::QtcProcess *process, + const QString &arguments, const QString &sourceDirectory, const QDir &buildDirectory, const Utils::Environment &env, diff --git a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp index b72443ea6c23a0aeddade1bd23a9ad86ef189eda..f1f34bc969313cc9586b9db681549bb051450cd6 100644 --- a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp @@ -141,14 +141,9 @@ QString CMakeRunConfiguration::baseWorkingDirectory() const return m_workingDirectory; } -QStringList CMakeRunConfiguration::commandLineArguments() const +QString CMakeRunConfiguration::commandLineArguments() const { - return environment().expandVariables(baseCommandLineArguments()); -} - -QStringList CMakeRunConfiguration::baseCommandLineArguments() const -{ - return Utils::Environment::parseCombinedArgString(m_arguments); + return m_arguments; } QString CMakeRunConfiguration::title() const @@ -329,7 +324,7 @@ CMakeRunConfigurationWidget::CMakeRunConfigurationWidget(CMakeRunConfiguration * fl->setMargin(0); fl->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow); QLineEdit *argumentsLineEdit = new QLineEdit(); - argumentsLineEdit->setText(Utils::Environment::joinArgumentList(cmakeRunConfiguration->baseCommandLineArguments())); + argumentsLineEdit->setText(cmakeRunConfiguration->commandLineArguments()); connect(argumentsLineEdit, SIGNAL(textChanged(QString)), this, SLOT(setArguments(QString))); fl->addRow(tr("Arguments:"), argumentsLineEdit); diff --git a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h index 8a84f0dc11a03b76216824dbddd1ebac8eb8c3d0..de5971ac0758db7a5d175d65d88460cce37d7bfe 100644 --- a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h +++ b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.h @@ -68,7 +68,7 @@ public: QString executable() const; RunMode runMode() const; QString workingDirectory() const; - QStringList commandLineArguments() const; + QString commandLineArguments() const; Utils::Environment environment() const; QWidget *createConfigurationWidget(); @@ -104,7 +104,6 @@ protected: private: void setUserWorkingDirectory(const QString &workingDirectory); QString baseWorkingDirectory() const; - QStringList baseCommandLineArguments() const; void ctor(); enum BaseEnvironmentBase { CleanEnvironmentBase = 0, diff --git a/src/plugins/cmakeprojectmanager/cmaketarget.cpp b/src/plugins/cmakeprojectmanager/cmaketarget.cpp index 705eb223bd9c1c701845c3c51ed67d977715b6a8..c223cd4c7df92511964d82763883aa26d7dc86ea 100644 --- a/src/plugins/cmakeprojectmanager/cmaketarget.cpp +++ b/src/plugins/cmakeprojectmanager/cmaketarget.cpp @@ -209,7 +209,7 @@ CMakeTarget *CMakeTargetFactory::create(ProjectExplorer::Project *parent, const MakeStep *cleanMakeStep = new MakeStep(cleanSteps); cleanSteps->insertStep(0, cleanMakeStep); - cleanMakeStep->setAdditionalArguments(QStringList() << "clean"); + cleanMakeStep->setAdditionalArguments("clean"); cleanMakeStep->setClean(true); t->addBuildConfiguration(bc); diff --git a/src/plugins/cmakeprojectmanager/makestep.cpp b/src/plugins/cmakeprojectmanager/makestep.cpp index 5689bcdbba6d79d749b587746e3574415674669d..1f1b1e763246fa1c7fdfa1201f8388eb4a7dc0a7 100644 --- a/src/plugins/cmakeprojectmanager/makestep.cpp +++ b/src/plugins/cmakeprojectmanager/makestep.cpp @@ -39,6 +39,8 @@ #include <projectexplorer/projectexplorer.h> #include <projectexplorer/gnumakeparser.h> +#include <utils/qtcprocess.h> + #include <QtGui/QFormLayout> #include <QtGui/QGroupBox> #include <QtGui/QCheckBox> @@ -78,7 +80,7 @@ MakeStep::MakeStep(BuildStepList *bsl, MakeStep *bs) : m_clean(bs->m_clean), m_futureInterface(0), m_buildTargets(bs->m_buildTargets), - m_additionalArguments(bs->m_buildTargets) + m_additionalArguments(Utils::QtcProcess::joinArgs(bs->m_buildTargets)) { ctor(); } @@ -117,7 +119,7 @@ bool MakeStep::fromMap(const QVariantMap &map) { m_clean = map.value(QLatin1String(CLEAN_KEY)).toBool(); m_buildTargets = map.value(QLatin1String(BUILD_TARGETS_KEY)).toStringList(); - m_additionalArguments = map.value(QLatin1String(ADDITIONAL_ARGUMENTS_KEY)).toStringList(); + m_additionalArguments = map.value(QLatin1String(ADDITIONAL_ARGUMENTS_KEY)).toString(); return BuildStep::fromMap(map); } @@ -132,8 +134,8 @@ bool MakeStep::init() setCommand(bc->toolChain()->makeCommand()); - QStringList arguments = m_buildTargets; - arguments << additionalArguments(); + QString arguments = Utils::QtcProcess::joinArgs(m_buildTargets); + Utils::QtcProcess::addArgs(&arguments, additionalArguments()); setArguments(arguments); setEnvironment(bc->environment()); setIgnoreReturnValue(m_clean); @@ -191,12 +193,12 @@ void MakeStep::setBuildTarget(const QString &buildTarget, bool on) m_buildTargets = old; } -QStringList MakeStep::additionalArguments() const +QString MakeStep::additionalArguments() const { return m_additionalArguments; } -void MakeStep::setAdditionalArguments(const QStringList &list) +void MakeStep::setAdditionalArguments(const QString &list) { m_additionalArguments = list; } @@ -239,7 +241,7 @@ MakeStepConfigWidget::MakeStepConfigWidget(MakeStep *makeStep) void MakeStepConfigWidget::additionalArgumentsEdited() { - m_makeStep->setAdditionalArguments(Utils::Environment::parseCombinedArgString(m_additionalArguments->text())); + m_makeStep->setAdditionalArguments(m_additionalArguments->text()); updateDetails(); } @@ -266,7 +268,7 @@ void MakeStepConfigWidget::init() // and connect again connect(m_buildTargetsList, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*))); - m_additionalArguments->setText(Utils::Environment::joinArgumentList(m_makeStep->additionalArguments())); + m_additionalArguments->setText(m_makeStep->additionalArguments()); updateDetails(); CMakeProject *pro = m_makeStep->cmakeBuildConfiguration()->cmakeTarget()->cmakeProject(); @@ -290,13 +292,13 @@ void MakeStepConfigWidget::buildTargetsChanged() void MakeStepConfigWidget::updateDetails() { - QStringList arguments = m_makeStep->m_buildTargets; - arguments << m_makeStep->additionalArguments(); + QString arguments = Utils::QtcProcess::joinArgs(m_makeStep->m_buildTargets); + Utils::QtcProcess::addArgs(&arguments, m_makeStep->additionalArguments()); CMakeBuildConfiguration *bc = m_makeStep->cmakeBuildConfiguration(); ProjectExplorer::ToolChain *tc = bc->toolChain(); if (tc) - m_summaryText = tr("<b>Make:</b> %1 %2").arg(tc->makeCommand(), arguments.join(QString(QLatin1Char(' ')))); + m_summaryText = tr("<b>Make:</b> %1 %2").arg(tc->makeCommand(), arguments); else m_summaryText = tr("<b>Unknown Toolchain</b>"); emit updateSummary(); diff --git a/src/plugins/cmakeprojectmanager/makestep.h b/src/plugins/cmakeprojectmanager/makestep.h index c0ac7bfe97b21caeb18c050f9e0dab0d8eff6896..7da6042d25f5d54e988d124532fc02767a622537 100644 --- a/src/plugins/cmakeprojectmanager/makestep.h +++ b/src/plugins/cmakeprojectmanager/makestep.h @@ -65,8 +65,8 @@ public: virtual bool immutable() const; bool buildsBuildTarget(const QString &target) const; void setBuildTarget(const QString &target, bool on); - QStringList additionalArguments() const; - void setAdditionalArguments(const QStringList &list); + QString additionalArguments() const; + void setAdditionalArguments(const QString &list); void setClean(bool clean); @@ -88,7 +88,7 @@ private: QRegExp m_percentProgress; QFutureInterface<bool> *m_futureInterface; QStringList m_buildTargets; - QStringList m_additionalArguments; + QString m_additionalArguments; }; class MakeStepConfigWidget :public ProjectExplorer::BuildStepConfigWidget diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index ab09bce6e5fbc21e863146b14bebffa51b9ccdd3..bc0a100c8d754f5a4be40797dfa8f97ad20de802 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -56,6 +56,7 @@ #include <coreplugin/icore.h> #include <utils/qtcassert.h> +#include <utils/qtcprocess.h> #include <utils/winutils.h> #include <utils/consoleprocess.h> #include <utils/fancymainwindow.h> @@ -464,7 +465,17 @@ void CdbEngine::runEngine() needWatchTimer = true; // Fetch away module load, etc. even if crashed break; case StartInternal: - case StartExternal: + case StartExternal: { + Utils::QtcProcess::SplitError perr; + QString pargs = Utils::QtcProcess::prepareArgs(sp.processArgs, &perr, + &sp.environment, &sp.workingDirectory); + if (perr != Utils::QtcProcess::SplitOk) { + // perr == BadQuoting is never returned on Windows + // FIXME? QTCREATORBUG-2809 + errorMessage = QApplication::translate("DebuggerEngine", // Same message in GdbEngine + "Debugging complex command lines is currently not supported under Windows"); + break; + } if (sp.useTerminal) { // Attaching to console processes triggers an initial breakpoint, which we do not want m_d->m_ignoreInitialBreakPoint = true; @@ -472,7 +483,7 @@ void CdbEngine::runEngine() m_d->m_consoleStubProc.stop(); // We leave the console open, so recycle it now. m_d->m_consoleStubProc.setWorkingDirectory(sp.workingDirectory); m_d->m_consoleStubProc.setEnvironment(sp.environment); - rc = m_d->m_consoleStubProc.start(sp.executable, sp.processArgs); + rc = m_d->m_consoleStubProc.start(sp.executable, pargs); if (!rc) errorMessage = tr("The console stub process was unable to start '%1'.").arg(sp.executable); // continues in slotConsoleStubStarted()... @@ -480,11 +491,11 @@ void CdbEngine::runEngine() needWatchTimer = true; rc = m_d->startDebuggerWithExecutable(sp.workingDirectory, sp.executable, - sp.processArgs, - sp.environment, + pargs, + sp.environment.toStringList(), &errorMessage); } - break; + break; } case AttachCore: errorMessage = tr("Attaching to core files is not supported."); break; diff --git a/src/plugins/debugger/cdb/coreengine.cpp b/src/plugins/debugger/cdb/coreengine.cpp index f4b4168bdee7df463faccddbd4f7730b7d910d0a..0b47cfe6f1c9435571e4b2ca7a382064d114da96 100644 --- a/src/plugins/debugger/cdb/coreengine.cpp +++ b/src/plugins/debugger/cdb/coreengine.cpp @@ -465,7 +465,7 @@ void CoreEngine::resetModuleLoadTimer() bool CoreEngine::startDebuggerWithExecutable(const QString &workingDirectory, const QString &filename, - const QStringList &args, + const QString &args, const QStringList &envList, QString *errorMessage) { diff --git a/src/plugins/debugger/cdb/coreengine.h b/src/plugins/debugger/cdb/coreengine.h index 36d8e9601f6c0687c9ea399e75258e9e703c8ff6..1b3f83c7b8ed370ebe1735055ff197a32218bf39 100644 --- a/src/plugins/debugger/cdb/coreengine.h +++ b/src/plugins/debugger/cdb/coreengine.h @@ -86,7 +86,7 @@ public: // Start functions bool startDebuggerWithExecutable(const QString &workingDirectory, const QString &filename, - const QStringList &args, + const QString &args, const QStringList &env, QString *errorMessage); diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index d489b92b11c5d3b27ce6743d71b6caa9c2405a2b..8bc54a88f0dd284861ff9cabf24ee02cd5fde57f 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -118,10 +118,9 @@ QDebug operator<<(QDebug d, DebuggerState state) QDebug operator<<(QDebug str, const DebuggerStartParameters &sp) { QDebug nospace = str.nospace(); - const QString sep = QString(QLatin1Char(',')); nospace << "executable=" << sp.executable << " coreFile=" << sp.coreFile - << " processArgs=" << sp.processArgs.join(sep) + << " processArgs=" << sp.processArgs << " environment=<" << sp.environment.size() << " variables>" << " workingDir=" << sp.workingDirectory << " attachPID=" << sp.attachPID @@ -477,8 +476,8 @@ void DebuggerEngine::startDebugger(DebuggerRunControl *runControl) d->m_inferiorPid = d->m_startParameters.attachPID > 0 ? d->m_startParameters.attachPID : 0; - if (d->m_startParameters.environment.empty()) - d->m_startParameters.environment = Utils::Environment().toStringList(); + if (!d->m_startParameters.environment.size()) + d->m_startParameters.environment = Utils::Environment(); if (d->m_startParameters.breakAtMain) breakByFunctionMain(); diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index cb439dd387eba238a689a67f7631e98ff3ba5036..4ebf9f731a105c5aafd018f8f29fd49d23f002a5 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -37,6 +37,8 @@ #include <coreplugin/ssh/sshconnection.h> +#include <utils/environment.h> + #include <QtCore/QObject> #include <QtCore/QStringList> @@ -70,8 +72,8 @@ public: QString displayName; QString coreFile; bool isSnapshot; // set if created internally - QStringList processArgs; - QStringList environment; + QString processArgs; + Utils::Environment environment; QString workingDirectory; qint64 attachPID; bool useTerminal; diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 8dc968c065d3eb0f70150206bf7edae502d7daab..bd89729453c5a315f2d39e4322f7a86f53296769 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -2047,10 +2047,9 @@ void DebuggerPluginPrivate::startExternalApplication() sp.workingDirectory = dlg.workingDirectory(); sp.breakAtMain = dlg.breakAtMain(); if (!dlg.executableArguments().isEmpty()) - sp.processArgs = dlg.executableArguments().split(QLatin1Char(' ')); + sp.processArgs = dlg.executableArguments(); // Fixme: 1 of 3 testing hacks. - if (!sp.processArgs.isEmpty() - && (sp.processArgs.front() == _("@tcf@") || sp.processArgs.front() == _("@sym@"))) + if (sp.processArgs.startsWith(__("@tcf@ ")) || sp.processArgs.startsWith(__("@sym@ "))) sp.toolChainType = ProjectExplorer::ToolChain_RVCT_ARMV5; diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index 5362ecc261d403eddd3e897e0d9e99728dc5d5bc..2c1a6240aea94b042756aafeda6cbbfb0ab944a3 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -171,7 +171,7 @@ static DebuggerStartParameters localStartParameters(RunConfiguration *runConfigu QTC_ASSERT(rc, return sp); sp.startMode = StartInternal; - sp.environment = rc->environment().toStringList(); + sp.environment = rc->environment(); sp.workingDirectory = rc->workingDirectory(); sp.executable = rc->executable(); sp.processArgs = rc->commandLineArguments(); @@ -429,7 +429,7 @@ void DebuggerRunControl::createEngine(const DebuggerStartParameters &startParams } // Fixme: 1 of 3 testing hacks. - if (sp.processArgs.size() >= 5 && sp.processArgs.at(0) == _("@tcf@")) + if (sp.processArgs.startsWith(__("@tcf@ "))) engineType = GdbEngineType; if (sp.processArgs.contains( _("@lldb@"))) @@ -525,7 +525,7 @@ QString DebuggerRunControl::displayName() const void DebuggerRunControl::setCustomEnvironment(Utils::Environment env) { - d->m_engine->startParameters().environment = env.toStringList(); + d->m_engine->startParameters().environment = env; } bool DebuggerRunControl::checkDebugConfiguration(int toolChain, diff --git a/src/plugins/debugger/gdb/abstractgdbadapter.cpp b/src/plugins/debugger/gdb/abstractgdbadapter.cpp index b0f80d39f85858a181219e713485b0943cd53b5d..2454dde0edcd7c9e8e76eabf758d6d15add38cec 100644 --- a/src/plugins/debugger/gdb/abstractgdbadapter.cpp +++ b/src/plugins/debugger/gdb/abstractgdbadapter.cpp @@ -32,6 +32,9 @@ #include "abstractgdbprocess.h" #include <utils/qtcassert.h> +#ifdef Q_OS_WIN +#include <utils/qtcprocess.h> +#endif #include <QtCore/QProcess> @@ -74,6 +77,24 @@ bool AbstractGdbAdapter::isTrkAdapter() const return false; } +#ifdef Q_OS_WIN +bool AbstractGdbAdapter::prepareWinCommand() +{ + Utils::QtcProcess::SplitError perr; + startParameters().processArgs = Utils::QtcProcess::prepareArgs( + startParameters().processArgs, &perr, + &startParameters().environment, &startParameters().workingDirectory); + if (perr != Utils::QtcProcess::SplitOk) { + // perr == BadQuoting is never returned on Windows + // FIXME? QTCREATORBUG-2809 + m_engine->handleAdapterStartFailed(QApplication::translate("DebuggerEngine", // Same message in CdbEngine + "Debugging complex command lines is currently not supported under Windows"), QString()); + return false; + } + return true; +} +#endif + QString AbstractGdbAdapter::msgGdbStopFailed(const QString &why) { return tr("The Gdb process could not be stopped:\n%1").arg(why); diff --git a/src/plugins/debugger/gdb/abstractgdbadapter.h b/src/plugins/debugger/gdb/abstractgdbadapter.h index 82e8676a8aa8c64c40ae6e523ecd4429911ef44f..033f51cac37fdf4c7fddcde196e771a15d93caa0 100644 --- a/src/plugins/debugger/gdb/abstractgdbadapter.h +++ b/src/plugins/debugger/gdb/abstractgdbadapter.h @@ -95,6 +95,9 @@ protected: const DebuggerStartParameters &startParameters() const; DebuggerStartParameters &startParameters(); void showMessage(const QString &msg, int channel = LogDebug, int timeout = 1); +#ifdef Q_OS_WIN + bool prepareWinCommand(); +#endif GdbEngine * const m_engine; }; diff --git a/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp b/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp index e4e7ea16a93aafc468eb5929c658fcf5d3d481dd..6fdcf482b7d6c5789ef33d237c6ba2c95aa7527a 100644 --- a/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp +++ b/src/plugins/debugger/gdb/abstractplaingdbadapter.cpp @@ -53,7 +53,7 @@ void AbstractPlainGdbAdapter::setupInferior() { QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state()); if (!startParameters().processArgs.isEmpty()) { - QString args = startParameters().processArgs.join(_(" ")); + QString args = startParameters().processArgs; m_engine->postCommand("-exec-arguments " + toLocalEncoding(args)); } m_engine->postCommand("-file-exec-and-symbols \"" + execFilePath() + '"', diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 2b71b9b2e67d3bd7b07453619592e7d85e3e50cf..25935c654b20a448c55612ff8a5f271759bacc70 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1708,7 +1708,7 @@ AbstractGdbAdapter *GdbEngine::createAdapter() case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC: case ProjectExplorer::ToolChain_GCCE_GNUPOC: // fixme: 1 of 3 testing hacks - if (sp.processArgs.size() >= 5 && sp.processArgs.at(0) == _("@tcf@")) + if (sp.processArgs.startsWith(__("@tcf@ "))) return new TcfTrkGdbAdapter(this); return new TrkGdbAdapter(this); default: diff --git a/src/plugins/debugger/gdb/localplaingdbadapter.cpp b/src/plugins/debugger/gdb/localplaingdbadapter.cpp index 89a8d549abf08a87ed89c84917c093cf8fc33521..a33a1771264d0768c12628e6a2cc1d94e2e04757 100644 --- a/src/plugins/debugger/gdb/localplaingdbadapter.cpp +++ b/src/plugins/debugger/gdb/localplaingdbadapter.cpp @@ -72,6 +72,11 @@ void LocalPlainGdbAdapter::startAdapter() QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state()); showMessage(_("TRYING TO START ADAPTER")); +#ifdef Q_OS_WIN + if (!prepareWinCommand()) + return; +#endif + QStringList gdbArgs; if (!m_outputCollector.listen()) { @@ -83,8 +88,8 @@ void LocalPlainGdbAdapter::startAdapter() if (!startParameters().workingDirectory.isEmpty()) m_gdbProc.setWorkingDirectory(startParameters().workingDirectory); - if (!startParameters().environment.isEmpty()) - m_gdbProc.setEnvironment(startParameters().environment); + if (startParameters().environment.size()) + m_gdbProc.setEnvironment(startParameters().environment.toStringList()); if (!m_engine->startGdb(gdbArgs)) { m_outputCollector.shutdown(); diff --git a/src/plugins/debugger/gdb/remotegdbprocess.cpp b/src/plugins/debugger/gdb/remotegdbprocess.cpp index 4ad44945df3473f9b850c92e3b6f880a2d944eca..c88c0ba2d3f450cfff711a90ca9a28184331b1de 100644 --- a/src/plugins/debugger/gdb/remotegdbprocess.cpp +++ b/src/plugins/debugger/gdb/remotegdbprocess.cpp @@ -32,6 +32,7 @@ #include "remoteplaingdbadapter.h" #include <utils/qtcassert.h> +#include <utils/qtcprocess.h> #include <QtCore/QFileInfo> @@ -143,11 +144,11 @@ void RemoteGdbProcess::handleAppOutputReaderStarted() connect(m_appOutputReader.data(), SIGNAL(outputAvailable(QByteArray)), this, SLOT(handleAppOutput(QByteArray))); - QByteArray cmdLine = "DISPLAY=:0.0 " + m_command.toUtf8() + ' ' - + m_cmdArgs.join(QLatin1String(" ")).toUtf8() + QByteArray cmdLine = "DISPLAY=:0.0 " + Utils::QtcProcess::quoteArgUnix(m_command).toUtf8() + ' ' + + Utils::QtcProcess::joinArgsUnix(m_cmdArgs).toUtf8() + " -tty=" + m_appOutputFileName; if (!m_wd.isEmpty()) - cmdLine.prepend("cd " + m_wd.toUtf8() + " && "); + cmdLine.prepend("cd " + Utils::QtcProcess::quoteArgUnix(m_wd).toUtf8() + " && "); m_gdbProc = m_conn->createRemoteProcess(cmdLine); connect(m_gdbProc.data(), SIGNAL(started()), this, SLOT(handleGdbStarted())); diff --git a/src/plugins/debugger/gdb/remotegdbserveradapter.cpp b/src/plugins/debugger/gdb/remotegdbserveradapter.cpp index 006dbb2ab72187f2644184d64e5e03da998d198c..629c744372fef63ca558ca37a52af6726be5abca 100644 --- a/src/plugins/debugger/gdb/remotegdbserveradapter.cpp +++ b/src/plugins/debugger/gdb/remotegdbserveradapter.cpp @@ -176,7 +176,7 @@ void RemoteGdbServerAdapter::setupInferior() const QByteArray gnuTarget = startParameters().gnuTarget.toLatin1(); const QByteArray solibPath = QFileInfo(startParameters().dumperLibrary).path().toLocal8Bit(); - const QString args = startParameters().processArgs.join(_(" ")); + const QString args = startParameters().processArgs; if (!remoteArch.isEmpty()) m_engine->postCommand("set architecture " + remoteArch); diff --git a/src/plugins/debugger/gdb/remoteplaingdbadapter.cpp b/src/plugins/debugger/gdb/remoteplaingdbadapter.cpp index 8ad74bdac820b7551c94c67c67303987b0113024..559bb0bd80378a37cfa4cba26143ce3288fae9c0 100644 --- a/src/plugins/debugger/gdb/remoteplaingdbadapter.cpp +++ b/src/plugins/debugger/gdb/remoteplaingdbadapter.cpp @@ -109,8 +109,8 @@ void RemotePlainGdbAdapter::handleSetupDone(int qmlPort) startParameters().qmlServerPort = qmlPort; if (!startParameters().workingDirectory.isEmpty()) m_gdbProc.setWorkingDirectory(startParameters().workingDirectory); - if (!startParameters().environment.isEmpty()) - m_gdbProc.setEnvironment(startParameters().environment); + if (startParameters().environment.size()) + m_gdbProc.setEnvironment(startParameters().environment.toStringList()); m_gdbProc.realStart(m_engine->startParameters().debuggerCommand, QStringList() << QLatin1String("-i") << QLatin1String("mi"), m_engine->startParameters().executable); diff --git a/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp b/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp index cf2b8c30074c0ed82ca339787617ae8a9f7d6bec..890b79a13f75daec04d8e10074ad990b2d39885f 100644 --- a/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp +++ b/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp @@ -44,6 +44,7 @@ #include <utils/qtcassert.h> #include <utils/savedaction.h> +#include <utils/qtcprocess.h> #include <QtCore/QTimer> #include <QtCore/QDir> @@ -971,7 +972,7 @@ void TcfTrkGdbAdapter::startAdapter() // Retrieve parameters const DebuggerStartParameters ¶meters = startParameters(); m_remoteExecutable = parameters.executable; - m_remoteArguments = parameters.processArgs; + m_remoteArguments = Utils::QtcProcess::splitArgs(parameters.processArgs); m_symbolFile = parameters.symbolFileName; QPair<QString, unsigned short> tcfTrkAddress; @@ -983,15 +984,15 @@ void TcfTrkGdbAdapter::startAdapter() if (debug) qDebug() << parameters.processArgs; // Fixme: 1 of 3 testing hacks. - if (parameters.processArgs.size() < 5 || parameters.processArgs.at(0) != _("@tcf@")) { + if (m_remoteArguments.size() < 5 || m_remoteArguments.at(0) != __("@tcf@")) { m_engine->handleAdapterStartFailed(_("Parameter error"), QString()); return; } - m_remoteExecutable = parameters.processArgs.at(1); - m_uid = parameters.processArgs.at(2).toUInt(0, 16); - m_symbolFile = parameters.processArgs.at(3); - tcfTrkAddress = splitIpAddressSpec(parameters.processArgs.at(4), 1534); + m_remoteExecutable = m_remoteArguments.at(1); + m_uid = m_remoteArguments.at(2).toUInt(0, 16); + m_symbolFile = m_remoteArguments.at(3); + tcfTrkAddress = splitIpAddressSpec(m_remoteArguments.at(4), 1534); m_remoteArguments.clear(); // Unixish gdbs accept only forward slashes diff --git a/src/plugins/debugger/gdb/termgdbadapter.cpp b/src/plugins/debugger/gdb/termgdbadapter.cpp index 1f9826d20dcdf7069cbf0ea9cdf364f7e6fe641f..64b1b6842103758a447b26d20d5bd4b11bbbdcce 100644 --- a/src/plugins/debugger/gdb/termgdbadapter.cpp +++ b/src/plugins/debugger/gdb/termgdbadapter.cpp @@ -96,10 +96,14 @@ void TermGdbAdapter::startAdapter() // m_stubProc.stop(); // m_stubProc.blockSignals(false); +#ifdef Q_OS_WIN + if (!prepareWinCommand()) + return; +#endif + m_stubProc.setWorkingDirectory(startParameters().workingDirectory); // Set environment + dumper preload. - QStringList environment = startParameters().environment; - m_stubProc.setEnvironment(environment); + m_stubProc.setEnvironment(startParameters().environment); // FIXME: Starting the stub implies starting the inferior. This is // fairly unclean as far as the state machine and error reporting go. if (!m_stubProc.start(startParameters().executable, diff --git a/src/plugins/debugger/gdb/trkgdbadapter.cpp b/src/plugins/debugger/gdb/trkgdbadapter.cpp index c5790f26f6de8efb8ff45bb66f660d8e43872bd6..8b235edfae1b4fffd5676a01d61b454b833904a7 100644 --- a/src/plugins/debugger/gdb/trkgdbadapter.cpp +++ b/src/plugins/debugger/gdb/trkgdbadapter.cpp @@ -46,6 +46,7 @@ #endif #include <utils/qtcassert.h> +#include <utils/qtcprocess.h> #include <utils/savedaction.h> #include <QtCore/QTimer> @@ -1551,10 +1552,11 @@ void TrkGdbAdapter::startAdapter() m_symbolFile = parameters.symbolFileName; QString remoteChannel = parameters.remoteChannel; // FIXME: testing hack, remove! - if (parameters.processArgs.size() >= 4 && parameters.processArgs.at(0) == _("@sym@")) { - remoteChannel = parameters.processArgs.at(1); - m_remoteExecutable = parameters.processArgs.at(2); - m_symbolFile = parameters.processArgs.at(3); + if (m_remoteArguments.startsWith(__("@sym@ "))) { + QStringList pa = Utils::QtcProcess::splitArgs(m_remoteArguments); + remoteChannel = pa.at(1); + m_remoteExecutable = pa.at(2); + m_symbolFile = pa.at(3); m_remoteArguments.clear(); } // Unixish gdbs accept only forward slashes diff --git a/src/plugins/debugger/gdb/trkgdbadapter.h b/src/plugins/debugger/gdb/trkgdbadapter.h index 93fadcccec95d8bcf9f9588049dac82dcc71ed4e..7c7905fbde369eaf0f950307c34eed91a4e2c3b3 100644 --- a/src/plugins/debugger/gdb/trkgdbadapter.h +++ b/src/plugins/debugger/gdb/trkgdbadapter.h @@ -224,7 +224,7 @@ private: trk::Session m_session; // global-ish data (process id, target information) Symbian::Snapshot m_snapshot; // local-ish data (memory and registers) QString m_remoteExecutable; - QStringList m_remoteArguments; + QString m_remoteArguments; QString m_symbolFile; int m_verbose; bool m_bufferedMemoryRead; diff --git a/src/plugins/debugger/lldb/ipcenginehost.cpp b/src/plugins/debugger/lldb/ipcenginehost.cpp index a654aa9bf5adabd81d6091bdbb23d84cec83114d..b8913655a1cae906c9ac8190534f84ce0a8c10ae 100644 --- a/src/plugins/debugger/lldb/ipcenginehost.cpp +++ b/src/plugins/debugger/lldb/ipcenginehost.cpp @@ -101,7 +101,7 @@ void IPCEngineHost::setupInferior() SET_NATIVE_BYTE_ORDER(s); s << QFileInfo(startParameters().executable).absoluteFilePath(); s << startParameters().processArgs; - s << startParameters().environment; + s << startParameters().environment.toStringList(); } rpcCall(SetupInferior, p); } diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index f75433b5cdf5cb86773ae562a85962892b20d780..006a15e5e4ae60ac9f021dcf235f81d0e62dc20d 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -791,13 +791,7 @@ bool QmlEngine::isShadowBuildProject() const QString QmlEngine::qmlImportPath() const { - const QString qmlImportPathPrefix("QML_IMPORT_PATH="); - QStringList env = startParameters().environment; - foreach (const QString &envStr, env) { - if (envStr.startsWith(qmlImportPathPrefix)) - return envStr.mid(qmlImportPathPrefix.length()); - } - return QString(); + return startParameters().environment.value("QML_IMPORT_PATH"); } QString QmlEngine::toShadowBuildFilename(const QString &filename) const diff --git a/src/plugins/genericprojectmanager/genericmakestep.cpp b/src/plugins/genericprojectmanager/genericmakestep.cpp index 5776f2593e8dd01f906fa6bd8f9e996078956031..f633144f4bd97fa4b1c6cfd6a75975dba9174cf8 100644 --- a/src/plugins/genericprojectmanager/genericmakestep.cpp +++ b/src/plugins/genericprojectmanager/genericmakestep.cpp @@ -42,6 +42,7 @@ #include <coreplugin/variablemanager.h> #include <utils/stringutils.h> #include <utils/qtcassert.h> +#include <utils/qtcprocess.h> #include <QtGui/QFormLayout> #include <QtGui/QGroupBox> @@ -132,26 +133,18 @@ QVariantMap GenericMakeStep::toMap() const bool GenericMakeStep::fromMap(const QVariantMap &map) { m_buildTargets = map.value(QLatin1String(BUILD_TARGETS_KEY)).toStringList(); - m_makeArguments = map.value(QLatin1String(MAKE_ARGUMENTS_KEY)).toStringList(); + m_makeArguments = map.value(QLatin1String(MAKE_ARGUMENTS_KEY)).toString(); m_makeCommand = map.value(QLatin1String(MAKE_COMMAND_KEY)).toString(); return BuildStep::fromMap(map); } -QStringList GenericMakeStep::replacedArguments() const +QString GenericMakeStep::replacedArguments() const { - Utils::AbstractMacroExpander *mx = Core::VariableManager::instance()->macroExpander(); - const QStringList targets = m_buildTargets; - QStringList arguments = m_makeArguments; - QStringList replacedArguments; - foreach (QString arg, arguments) { - Utils::expandMacros(&arg, mx); - replacedArguments << arg; - } - foreach (QString arg, targets) { - Utils::expandMacros(&arg, mx); - replacedArguments << arg; - } + QString replacedArguments = m_makeArguments; + Utils::QtcProcess::addArgs(&replacedArguments, m_buildTargets); + Utils::QtcProcess::expandMacros(&replacedArguments, + Core::VariableManager::instance()->macroExpander()); return replacedArguments; } @@ -245,11 +238,8 @@ void GenericMakeStepConfigWidget::init() { updateMakeOverrrideLabel(); - QString makeCommand = m_makeStep->m_makeCommand; - m_ui->makeLineEdit->setText(makeCommand); - - const QStringList &makeArguments = m_makeStep->m_makeArguments; - m_ui->makeArgumentsLineEdit->setText(Utils::Environment::joinArgumentList(makeArguments)); + m_ui->makeLineEdit->setText(m_makeStep->m_makeCommand); + m_ui->makeArgumentsLineEdit->setText(m_makeStep->m_makeArguments); // Disconnect to make the changes to the items disconnect(m_ui->targetsList, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*))); @@ -268,8 +258,7 @@ void GenericMakeStepConfigWidget::init() void GenericMakeStepConfigWidget::updateDetails() { m_summaryText = tr("<b>Make:</b> %1 %2") - .arg(m_makeStep->makeCommand(), - Utils::Environment::joinArgumentList(m_makeStep->replacedArguments())); + .arg(m_makeStep->makeCommand(), m_makeStep->replacedArguments()); emit updateSummary(); } @@ -292,8 +281,7 @@ void GenericMakeStepConfigWidget::makeLineEditTextEdited() void GenericMakeStepConfigWidget::makeArgumentsLineEditTextEdited() { - m_makeStep->m_makeArguments = - Utils::Environment::parseCombinedArgString(m_ui->makeArgumentsLineEdit->text()); + m_makeStep->m_makeArguments = m_ui->makeArgumentsLineEdit->text(); updateDetails(); } diff --git a/src/plugins/genericprojectmanager/genericmakestep.h b/src/plugins/genericprojectmanager/genericmakestep.h index 1326e5300554b2712c0f6a016dd4e0749970bc33..27830b69a09167bf478ec76e2ceb057f9c4d0097 100644 --- a/src/plugins/genericprojectmanager/genericmakestep.h +++ b/src/plugins/genericprojectmanager/genericmakestep.h @@ -67,7 +67,7 @@ public: virtual bool immutable() const; bool buildsTarget(const QString &target) const; void setBuildTarget(const QString &target, bool on); - QStringList replacedArguments() const; + QString replacedArguments() const; QString makeCommand() const; QVariantMap toMap() const; @@ -81,7 +81,7 @@ private: void ctor(); QStringList m_buildTargets; - QStringList m_makeArguments; + QString m_makeArguments; QString m_makeCommand; }; diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index fad4e9391ea3b6552d40a7c42da044d5791d1d41..3bf8ccdfac7c009222b7822fcbdf3919c9941618 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -49,6 +49,7 @@ #include <texteditor/itexteditor.h> #include <utils/qtcassert.h> +#include <utils/qtcprocess.h> #include <utils/synchronousprocess.h> #include <utils/environment.h> #include <vcsbase/vcsbaseeditor.h> @@ -1352,7 +1353,7 @@ bool GitClient::tryLauchingGitK(const QProcessEnvironment &env, #endif VCSBase::VCSBaseOutputWindow *outwin = VCSBase::VCSBaseOutputWindow::instance(); if (!m_settings.gitkOptions.isEmpty()) - arguments.append(m_settings.gitkOptions.split(QLatin1Char(' '))); + arguments.append(Utils::QtcProcess::splitArgs(m_settings.gitkOptions)); outwin->appendCommand(workingDirectory, binary, arguments); // This should always use QProcess::startDetached (as not to kill // the child), but that does not have an environment parameter. diff --git a/src/plugins/projectexplorer/abstractprocessstep.cpp b/src/plugins/projectexplorer/abstractprocessstep.cpp index 7234b0479b694f08cd316d93625aec4a63b7c511..0576acc3ca9dca0b44aa152fc429d52255d22bcc 100644 --- a/src/plugins/projectexplorer/abstractprocessstep.cpp +++ b/src/plugins/projectexplorer/abstractprocessstep.cpp @@ -35,6 +35,7 @@ #include "target.h" #include <utils/qtcassert.h> +#include <utils/qtcprocess.h> #include <QtCore/QEventLoop> #include <QtCore/QTimer> @@ -113,12 +114,12 @@ void AbstractProcessStep::setWorkingDirectory(const QString &workingDirectory) m_workingDirectory = workingDirectory; } -void AbstractProcessStep::setArguments(const QStringList &arguments) +void AbstractProcessStep::setArguments(const QString &arguments) { m_arguments = arguments; } -QStringList AbstractProcessStep::arguments() const +QString AbstractProcessStep::arguments() const { return m_arguments; } @@ -154,9 +155,9 @@ void AbstractProcessStep::run(QFutureInterface<bool> &fi) if (!wd.exists()) wd.mkpath(wd.absolutePath()); - m_process = new QProcess(); + m_process = new Utils::QtcProcess(); m_process->setWorkingDirectory(wd.absolutePath()); - m_process->setEnvironment(m_environment.toStringList()); + m_process->setEnvironment(m_environment); connect(m_process, SIGNAL(readyReadStandardOutput()), this, SLOT(processReadyReadStdOutput()), @@ -169,7 +170,8 @@ void AbstractProcessStep::run(QFutureInterface<bool> &fi) this, SLOT(slotProcessFinished(int, QProcess::ExitStatus)), Qt::DirectConnection); - m_process->start(expandedCommand(), m_environment.expandVariables(m_arguments)); + m_process->setCommand(expandedCommand(), m_arguments); + m_process->start(); if (!m_process->waitForStarted()) { processStartupFailed(); delete m_process; @@ -210,8 +212,7 @@ void AbstractProcessStep::run(QFutureInterface<bool> &fi) void AbstractProcessStep::processStarted() { emit addOutput(tr("Starting: \"%1\" %2\n") - .arg(QDir::toNativeSeparators(expandedCommand()), - m_environment.expandVariables(m_arguments).join(QChar(' '))), + .arg(QDir::toNativeSeparators(expandedCommand()), expandedArguments()), BuildStep::MessageOutput); } @@ -232,9 +233,8 @@ void AbstractProcessStep::processFinished(int exitCode, QProcess::ExitStatus sta void AbstractProcessStep::processStartupFailed() { - emit addOutput(tr("Could not start process \"%1\" %2"). - arg(QDir::toNativeSeparators(expandedCommand()), - m_environment.expandVariables(m_arguments).join(QChar(' '))), + emit addOutput(tr("Could not start process \"%1\" %2") + .arg(QDir::toNativeSeparators(expandedCommand()), expandedArguments()), BuildStep::ErrorMessageOutput); } @@ -359,3 +359,21 @@ QString AbstractProcessStep::expandedCommand() const command = m_command; return command; } + +QString AbstractProcessStep::expandedArguments() const +{ +#ifdef Q_OS_WIN + QString args; +#else + QStringList args; +#endif + Utils::QtcProcess::SplitError err; + args = Utils::QtcProcess::prepareArgs(m_arguments, &err, &m_environment); + if (err != Utils::QtcProcess::SplitOk) + return m_arguments; // Sorry, too complex - just fall back. +#ifdef Q_OS_WIN + return args; +#else + return Utils::QtcProcess::joinArgs(args); +#endif +} diff --git a/src/plugins/projectexplorer/abstractprocessstep.h b/src/plugins/projectexplorer/abstractprocessstep.h index 78e4723fa4c9bfe151e4cb7ab8c0e4e121d93571..bf079dae4b7158c1da63e489c1726f352db4b30d 100644 --- a/src/plugins/projectexplorer/abstractprocessstep.h +++ b/src/plugins/projectexplorer/abstractprocessstep.h @@ -34,8 +34,9 @@ #include <utils/environment.h> +#include <utils/qtcprocess.h> + #include <QtCore/QString> -#include <QtCore/QProcess> QT_BEGIN_NAMESPACE class QEventLoop; @@ -93,8 +94,8 @@ public: /// sets the command line arguments used by the process for a \p buildConfiguration /// should be called from init() - void setArguments(const QStringList &arguments); - QStringList arguments() const; + void setArguments(const QString &arguments); + QString arguments() const; /// enables or disables a BuildStep /// Disabled BuildSteps immediately return true from their run method @@ -125,6 +126,8 @@ protected: /// Get the fully expanded command name to run: QString expandedCommand() const; + /// Get the fully expanded command line args. This is for display purposes only! + QString expandedArguments() const; /// Called after the process is started /// the default implementation adds a process started message to the output message @@ -161,10 +164,10 @@ private: QFutureInterface<bool> *m_futureInterface; QString m_workingDirectory; QString m_command; - QStringList m_arguments; + QString m_arguments; bool m_enabled; bool m_ignoreReturnValue; - QProcess *m_process; + Utils::QtcProcess *m_process; QEventLoop *m_eventLoop; Utils::Environment m_environment; ProjectExplorer::IOutputParser *m_outputParserChain; diff --git a/src/plugins/projectexplorer/applicationlauncher.h b/src/plugins/projectexplorer/applicationlauncher.h index a35f654eaafae77ce2a4e44c9fa3d0eea65a70dc..4f7a2c9bdcadfb09326b4af8dac40f3e866710bc 100644 --- a/src/plugins/projectexplorer/applicationlauncher.h +++ b/src/plugins/projectexplorer/applicationlauncher.h @@ -32,12 +32,10 @@ #include "projectexplorer_export.h" -#include <QtCore/QObject> -#include <QtCore/QStringList> #include <QtCore/QProcess> namespace Utils { -class ConsoleProcess; +class Environment; } namespace ProjectExplorer { @@ -57,10 +55,10 @@ public: ~ApplicationLauncher(); void setWorkingDirectory(const QString &dir); - void setEnvironment(const QStringList &env); + void setEnvironment(const Utils::Environment &env); void start(Mode mode, const QString &program, - const QStringList &args = QStringList()); + const QString &args = QString()); void stop(); bool isRunning() const; qint64 applicationPID() const; diff --git a/src/plugins/projectexplorer/applicationlauncher_win.cpp b/src/plugins/projectexplorer/applicationlauncher_win.cpp index eb61352dcc4963047d0d7f3a0ba28c74fda75d24..e5df2b1b670f248cb4a22f26d478d68f72df29ad 100644 --- a/src/plugins/projectexplorer/applicationlauncher_win.cpp +++ b/src/plugins/projectexplorer/applicationlauncher_win.cpp @@ -69,13 +69,13 @@ void ApplicationLauncher::setWorkingDirectory(const QString &dir) d->m_consoleProcess.setWorkingDirectory(dir); } -void ApplicationLauncher::setEnvironment(const QStringList &env) +void ApplicationLauncher::setEnvironment(const Utils::Environment &env) { d->m_winGuiProcess.setEnvironment(env); d->m_consoleProcess.setEnvironment(env); } -void ApplicationLauncher::start(Mode mode, const QString &program, const QStringList &args) +void ApplicationLauncher::start(Mode mode, const QString &program, const QString &args) { d->m_currentMode = mode; if (mode == Gui) { diff --git a/src/plugins/projectexplorer/applicationlauncher_x11.cpp b/src/plugins/projectexplorer/applicationlauncher_x11.cpp index d058c96f95434263bb16493059ddf47837faed4b..63963b38780e33fb45ab6c6bfa4f9ebc6111e9e4 100644 --- a/src/plugins/projectexplorer/applicationlauncher_x11.cpp +++ b/src/plugins/projectexplorer/applicationlauncher_x11.cpp @@ -32,6 +32,8 @@ #include <coreplugin/icore.h> +#include <utils/qtcprocess.h> + #include <QtCore/QTimer> #include <QtCore/QTextCodec> @@ -40,7 +42,7 @@ namespace ProjectExplorer { struct ApplicationLauncherPrivate { ApplicationLauncherPrivate(); - QProcess m_guiProcess; + Utils::QtcProcess m_guiProcess; Utils::ConsoleProcess m_consoleProcess; ApplicationLauncher::Mode m_currentMode; @@ -87,17 +89,18 @@ void ApplicationLauncher::setWorkingDirectory(const QString &dir) d->m_consoleProcess.setWorkingDirectory(dir); } -void ApplicationLauncher::setEnvironment(const QStringList &env) +void ApplicationLauncher::setEnvironment(const Utils::Environment &env) { d->m_guiProcess.setEnvironment(env); d->m_consoleProcess.setEnvironment(env); } -void ApplicationLauncher::start(Mode mode, const QString &program, const QStringList &args) +void ApplicationLauncher::start(Mode mode, const QString &program, const QString &args) { d->m_currentMode = mode; if (mode == Gui) { - d->m_guiProcess.start(program, args); + d->m_guiProcess.setCommand(program, args); + d->m_guiProcess.start(); } else { d->m_consoleProcess.start(program, args); } diff --git a/src/plugins/projectexplorer/applicationrunconfiguration.cpp b/src/plugins/projectexplorer/applicationrunconfiguration.cpp index c1963bc065398bc233b57be9f0c8bd128398040e..7ad4c8fc5758231701f9ac288db65e31ecb2ad79 100644 --- a/src/plugins/projectexplorer/applicationrunconfiguration.cpp +++ b/src/plugins/projectexplorer/applicationrunconfiguration.cpp @@ -48,4 +48,3 @@ LocalApplicationRunConfiguration::~LocalApplicationRunConfiguration() } } // namespace ProjectExplorer - diff --git a/src/plugins/projectexplorer/applicationrunconfiguration.h b/src/plugins/projectexplorer/applicationrunconfiguration.h index 49092e260a5cff3af9a819e491bb8f8e065cafd8..c0e2323131fed783bdba94850864001b56e177d0 100644 --- a/src/plugins/projectexplorer/applicationrunconfiguration.h +++ b/src/plugins/projectexplorer/applicationrunconfiguration.h @@ -54,7 +54,7 @@ public: virtual QString executable() const = 0; virtual RunMode runMode() const = 0; virtual QString workingDirectory() const = 0; - virtual QStringList commandLineArguments() const = 0; + virtual QString commandLineArguments() const = 0; virtual Utils::Environment environment() const = 0; virtual QString dumperLibrary() const = 0; virtual QStringList dumperLibraryLocations() const = 0; diff --git a/src/plugins/projectexplorer/customexecutableconfigurationwidget.cpp b/src/plugins/projectexplorer/customexecutableconfigurationwidget.cpp index 2d1b3399a81d2909028decfeb2ce73906df0e99f..d4266937efad71f58c7a8d99ba31aad4643dae2d 100644 --- a/src/plugins/projectexplorer/customexecutableconfigurationwidget.cpp +++ b/src/plugins/projectexplorer/customexecutableconfigurationwidget.cpp @@ -231,7 +231,7 @@ void CustomExecutableConfigurationWidget::executableEdited() void CustomExecutableConfigurationWidget::argumentsEdited(const QString &arguments) { m_ignoreChange = true; - m_runConfiguration->setBaseCommandLineArguments(arguments); + m_runConfiguration->setCommandLineArguments(arguments); m_ignoreChange = false; } void CustomExecutableConfigurationWidget::workingDirectoryEdited() @@ -256,7 +256,7 @@ void CustomExecutableConfigurationWidget::changed() return; m_executableChooser->setPath(m_runConfiguration->rawExecutable()); - m_commandLineArgumentsLineEdit->setText(Utils::Environment::joinArgumentList(m_runConfiguration->baseCommandLineArguments())); + m_commandLineArgumentsLineEdit->setText(m_runConfiguration->commandLineArguments()); m_workingDirectory->setPath(m_runConfiguration->baseWorkingDirectory()); m_useTerminalCheck->setChecked(m_runConfiguration->runMode() == LocalApplicationRunConfiguration::Console); } diff --git a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp index dc353214b203b3164472b59550c1180723540de5..2890c8a7e464e27f3e78ca677f59fa4b9ba284c8 100644 --- a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp +++ b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp @@ -141,7 +141,7 @@ QString CustomExecutableRunConfiguration::executable() const QString oldExecutable = m_executable; QString oldWorkingDirectory = m_workingDirectory; - QStringList oldCmdArguments = m_cmdArguments; + QString oldCmdArguments = m_cmdArguments; if (dialog.exec()) { return executable(); @@ -183,12 +183,7 @@ QString CustomExecutableRunConfiguration::baseWorkingDirectory() const } -QStringList CustomExecutableRunConfiguration::commandLineArguments() const -{ - return environment().expandVariables(baseCommandLineArguments()); -} - -QStringList CustomExecutableRunConfiguration::baseCommandLineArguments() const +QString CustomExecutableRunConfiguration::commandLineArguments() const { return m_cmdArguments; } @@ -275,7 +270,7 @@ QVariantMap CustomExecutableRunConfiguration::toMap() const bool CustomExecutableRunConfiguration::fromMap(const QVariantMap &map) { m_executable = map.value(QLatin1String(EXECUTABLE_KEY)).toString(); - m_cmdArguments = map.value(QLatin1String(ARGUMENTS_KEY)).toStringList(); + m_cmdArguments = map.value(QLatin1String(ARGUMENTS_KEY)).toString(); m_workingDirectory = map.value(QLatin1String(WORKING_DIRECTORY_KEY)).toString(); m_runMode = map.value(QLatin1String(USE_TERMINAL_KEY)).toBool() ? Console : Gui; m_userEnvironmentChanges = Utils::EnvironmentItem::fromStringList(map.value(QLatin1String(USER_ENVIRONMENT_CHANGES_KEY)).toStringList()); @@ -294,9 +289,9 @@ void CustomExecutableRunConfiguration::setExecutable(const QString &executable) emit changed(); } -void CustomExecutableRunConfiguration::setBaseCommandLineArguments(const QString &commandLineArguments) +void CustomExecutableRunConfiguration::setCommandLineArguments(const QString &commandLineArguments) { - m_cmdArguments = Utils::Environment::parseCombinedArgString(commandLineArguments); + m_cmdArguments = commandLineArguments; emit changed(); } diff --git a/src/plugins/projectexplorer/customexecutablerunconfiguration.h b/src/plugins/projectexplorer/customexecutablerunconfiguration.h index f3287b65ba86ac8acc047f44b2df6c3d2c90afed..debbba3ca035c53e10f1860d2a273ff0f1f3415c 100644 --- a/src/plugins/projectexplorer/customexecutablerunconfiguration.h +++ b/src/plugins/projectexplorer/customexecutablerunconfiguration.h @@ -69,7 +69,7 @@ public: LocalApplicationRunConfiguration::RunMode runMode() const; QString workingDirectory() const; - QStringList commandLineArguments() const; + QString commandLineArguments() const; Utils::Environment environment() const; QWidget *createConfigurationWidget(); @@ -108,8 +108,7 @@ private: QList<Utils::EnvironmentItem> userEnvironmentChanges() const; void setExecutable(const QString &executable); - void setBaseCommandLineArguments(const QString &commandLineArguments); - QStringList baseCommandLineArguments() const; + void setCommandLineArguments(const QString &commandLineArguments); QString baseWorkingDirectory() const; void setBaseWorkingDirectory(const QString &workingDirectory); void setUserName(const QString &name); @@ -117,7 +116,7 @@ private: QString m_executable; QString m_workingDirectory; - QStringList m_cmdArguments; + QString m_cmdArguments; RunMode m_runMode; bool m_userSetName; QString m_userName; diff --git a/src/plugins/projectexplorer/foldernavigationwidget.cpp b/src/plugins/projectexplorer/foldernavigationwidget.cpp index 217d89173daadbdbf63716ab19153f239778d673..c4ffda25817643282e3c6fe3b8a12cb685934815 100644 --- a/src/plugins/projectexplorer/foldernavigationwidget.cpp +++ b/src/plugins/projectexplorer/foldernavigationwidget.cpp @@ -40,6 +40,7 @@ #include <utils/environment.h> #include <utils/pathchooser.h> #include <utils/qtcassert.h> +#include <utils/qtcprocess.h> #include <utils/unixutils.h> #include <utils/consoleprocess.h> @@ -438,8 +439,8 @@ void FolderNavigationWidget::openTerminal(const QString &path) const QString terminalEmulator = QString::fromLocal8Bit(qgetenv("COMSPEC")); const QStringList args; // none #else - QStringList args = Utils::ConsoleProcess::terminalEmulator( - Core::ICore::instance()->settings()).split(QLatin1Char(' ')); + QStringList args = Utils::QtcProcess::splitArgs( + Utils::ConsoleProcess::terminalEmulator(Core::ICore::instance()->settings())); const QString terminalEmulator = args.takeFirst(); const QString shell = QString::fromLocal8Bit(qgetenv("SHELL")); args.append(shell); diff --git a/src/plugins/projectexplorer/localapplicationruncontrol.cpp b/src/plugins/projectexplorer/localapplicationruncontrol.cpp index fda6752b7d03e51fa821d995ff35dcac65400d2e..c7cd867defca6dfada2a06f7c3e459e6e60809e4 100644 --- a/src/plugins/projectexplorer/localapplicationruncontrol.cpp +++ b/src/plugins/projectexplorer/localapplicationruncontrol.cpp @@ -78,7 +78,7 @@ LocalApplicationRunControl::LocalApplicationRunControl(LocalApplicationRunConfig { Utils::Environment env = rc->environment(); QString dir = rc->workingDirectory(); - m_applicationLauncher.setEnvironment(env.toStringList()); + m_applicationLauncher.setEnvironment(env); m_applicationLauncher.setWorkingDirectory(dir); m_executable = rc->executable(); diff --git a/src/plugins/projectexplorer/localapplicationruncontrol.h b/src/plugins/projectexplorer/localapplicationruncontrol.h index 3c546f0c3bc7819185721ff1429a9a97b22d9108..3445b05301ebfa9c02602f319db802ffd1928527 100644 --- a/src/plugins/projectexplorer/localapplicationruncontrol.h +++ b/src/plugins/projectexplorer/localapplicationruncontrol.h @@ -66,7 +66,7 @@ private slots: private: ProjectExplorer::ApplicationLauncher m_applicationLauncher; QString m_executable; - QStringList m_commandLineArguments; + QString m_commandLineArguments; ProjectExplorer::ApplicationLauncher::Mode m_runMode; }; diff --git a/src/plugins/projectexplorer/processstep.cpp b/src/plugins/projectexplorer/processstep.cpp index eca3efb90fa35699605c2250bdf37fc537dc59c1..3edb56e7de531f72641cc92de2c8769efcf0efcb 100644 --- a/src/plugins/projectexplorer/processstep.cpp +++ b/src/plugins/projectexplorer/processstep.cpp @@ -33,6 +33,7 @@ #include "buildconfiguration.h" #include <coreplugin/ifile.h> +#include <utils/qtcprocess.h> #include <utils/qtcassert.h> #include <QtCore/QDebug> @@ -124,7 +125,7 @@ QString ProcessStep::command() const return m_command; } -QStringList ProcessStep::arguments() const +QString ProcessStep::arguments() const { return m_arguments; } @@ -144,7 +145,7 @@ void ProcessStep::setCommand(const QString &command) m_command = command; } -void ProcessStep::setArguments(const QStringList &arguments) +void ProcessStep::setArguments(const QString &arguments) { m_arguments = arguments; } @@ -176,7 +177,7 @@ QVariantMap ProcessStep::toMap() const bool ProcessStep::fromMap(const QVariantMap &map) { setCommand(map.value(QLatin1String(PROCESS_COMMAND_KEY)).toString()); - setArguments(map.value(QLatin1String(PROCESS_ARGUMENTS_KEY)).toStringList()); + setArguments(map.value(QLatin1String(PROCESS_ARGUMENTS_KEY)).toString()); setWorkingDirectory(map.value(QLatin1String(PROCESS_WORKINGDIRECTORY_KEY)).toString()); setEnabled(map.value(QLatin1String(PROCESS_ENABLED_KEY), false).toBool()); return AbstractProcessStep::fromMap(map); @@ -277,7 +278,7 @@ void ProcessStepConfigWidget::updateDetails() m_summaryText = tr("<b>%1</b> %2 %3 %4") .arg(displayName, m_step->command(), - m_step->arguments().join(QString(QLatin1Char(' '))), + m_step->arguments(), m_step->enabled() ? QString() : tr("(disabled)")); emit updateSummary(); } @@ -295,7 +296,7 @@ void ProcessStepConfigWidget::init() m_ui.workingDirectory->setEnvironment(m_step->buildConfiguration()->environment()); m_ui.workingDirectory->setPath(m_step->workingDirectory()); - m_ui.commandArgumentsLineEdit->setText(m_step->arguments().join(QString(QLatin1Char(' ')))); + m_ui.commandArgumentsLineEdit->setText(m_step->arguments()); m_ui.enabledCheckBox->setChecked(m_step->enabled()); updateDetails(); @@ -319,8 +320,7 @@ void ProcessStepConfigWidget::workingDirectoryLineEditTextEdited() void ProcessStepConfigWidget::commandArgumentsLineEditTextEdited() { - m_step->setArguments(m_ui.commandArgumentsLineEdit->text().split(QLatin1Char(' '), - QString::SkipEmptyParts)); + m_step->setArguments(m_ui.commandArgumentsLineEdit->text()); updateDetails(); } diff --git a/src/plugins/projectexplorer/processstep.h b/src/plugins/projectexplorer/processstep.h index e6c865cc148e6d411f7e95c0df324e2b668ca333..f38ad0b7c756d1929ce4fb2ca8949e65e5d845cf 100644 --- a/src/plugins/projectexplorer/processstep.h +++ b/src/plugins/projectexplorer/processstep.h @@ -73,12 +73,12 @@ public: virtual bool immutable() const; QString command() const; - QStringList arguments() const; + QString arguments() const; bool enabled() const; QString workingDirectory() const; void setCommand(const QString &command); - void setArguments(const QStringList &arguments); + void setArguments(const QString &arguments); void setEnabled(bool enabled); void setWorkingDirectory(const QString &workingDirectory); @@ -94,7 +94,7 @@ private: void ctor(); QString m_command; - QStringList m_arguments; + QString m_arguments; QString m_workingDirectory; Utils::Environment m_env; bool m_enabled; diff --git a/src/plugins/projectexplorer/toolchain.cpp b/src/plugins/projectexplorer/toolchain.cpp index 16ee9c4668527f9a3d895dadfb3ca909aa070c00..8fe844ddbe1503a5b8471ce328e526cc51dac7ac 100644 --- a/src/plugins/projectexplorer/toolchain.cpp +++ b/src/plugins/projectexplorer/toolchain.cpp @@ -35,8 +35,8 @@ #include "msvcparser.h" #include "linuxiccparser.h" - #include <utils/synchronousprocess.h> +#include <utils/qtcprocess.h> #include <QtCore/QDebug> #include <QtCore/QFileInfo> @@ -768,16 +768,16 @@ MSVCToolChain::StringStringPairList MSVCToolChain::readEnvironmentSettingI(const if (!tf.open()) return StringStringPairList(); const QString filename = tf.fileName(); - QByteArray call = "call \""; - call += varsBat.toLocal8Bit(); - call += '"'; + QByteArray call = "call "; + call += Utils::QtcProcess::quoteArg(varsBat).toLocal8Bit(); if (!args.isEmpty()) { call += ' '; - call += args.join(QString(QLatin1Char(' '))).toLocal8Bit(); + call += Utils::QtcProcess::joinArgs(args).toLocal8Bit(); } call += "\r\n"; tf.write(call); - const QByteArray redirect = "set > \"" + QDir::toNativeSeparators(tempOutputFileName).toLocal8Bit() + "\"\r\n"; + const QByteArray redirect = "set > " + Utils::QtcProcess::quoteArg( + QDir::toNativeSeparators(tempOutputFileName)).toLocal8Bit() + "\r\n"; tf.write(redirect); tf.flush(); tf.waitForBytesWritten(30000); diff --git a/src/plugins/projectexplorer/winguiprocess.cpp b/src/plugins/projectexplorer/winguiprocess.cpp index 3317ce317bcf8f77be65d059e365f70803550e7d..97e8170d70bd226cc7ebc7a22940b08914c5f578 100644 --- a/src/plugins/projectexplorer/winguiprocess.cpp +++ b/src/plugins/projectexplorer/winguiprocess.cpp @@ -30,6 +30,8 @@ #include "winguiprocess.h" #include "consoleprocess.h" +#include <utils/qtcprocess.h> + #include <QtCore/QDir> using namespace ProjectExplorer::Internal; @@ -46,7 +48,7 @@ WinGuiProcess::~WinGuiProcess() stop(); } -bool WinGuiProcess::start(const QString &program, const QStringList &args) +bool WinGuiProcess::start(const QString &program, const QString &args) { m_program = program; m_args = args; @@ -112,11 +114,14 @@ void WinGuiProcess::run() const bool dbgInterface = setupDebugInterface(bufferReadyEvent, dataReadyEvent, sharedFile, sharedMem); - const QString cmdLine = createWinCommandline(m_program, m_args); + QString pcmd, pargs; + QtcProcess::prepareCommand(m_program, m_args, &pcmd, &pargs, &m_environment, &m_workingDir); + const QString cmdLine = createWinCommandline(pcmd, pargs); + const QStringList env = m_environment.toStringList(); started = CreateProcessW(0, (WCHAR*)cmdLine.utf16(), 0, 0, TRUE, CREATE_UNICODE_ENVIRONMENT, - environment().isEmpty() ? 0 - : createWinEnvironment(fixWinEnvironment(environment())).data(), + env.isEmpty() ? 0 + : createWinEnvironment(fixWinEnvironment(env)).data(), workingDirectory().isEmpty() ? 0 : (WCHAR*)QDir::convertSeparators(workingDirectory()).utf16(), &si, m_pid); diff --git a/src/plugins/projectexplorer/winguiprocess.h b/src/plugins/projectexplorer/winguiprocess.h index e729317dd2d31746b1afcf65f750b7f011370ea0..3e63439018546e64bca3c4d2a5326e813eab1657 100644 --- a/src/plugins/projectexplorer/winguiprocess.h +++ b/src/plugins/projectexplorer/winguiprocess.h @@ -53,7 +53,7 @@ public: explicit WinGuiProcess(QObject *parent = 0); virtual ~WinGuiProcess(); - bool start(const QString &program, const QStringList &args); + bool start(const QString &program, const QString &args); void stop(); bool isRunning() const; @@ -71,7 +71,7 @@ private: PROCESS_INFORMATION *m_pid; QString m_program; - QStringList m_args; + QString m_args; unsigned long m_exitCode; }; diff --git a/src/plugins/qmljseditor/qmljspreviewrunner.cpp b/src/plugins/qmljseditor/qmljspreviewrunner.cpp index 585b2e3b18ce0fd1c4ed7cc6a7a587d6f7a2dd8e..c16e528ed63ab6bf2b15adf9668ddb67420aaef8 100644 --- a/src/plugins/qmljseditor/qmljspreviewrunner.cpp +++ b/src/plugins/qmljseditor/qmljspreviewrunner.cpp @@ -30,6 +30,7 @@ #include "qmljspreviewrunner.h" #include <utils/environment.h> +#include <utils/qtcprocess.h> #include <utils/synchronousprocess.h> #include <QtGui/QMessageBox> @@ -50,7 +51,7 @@ QmlJSPreviewRunner::QmlJSPreviewRunner(QObject *parent) : m_qmlViewerDefaultPath = Utils::SynchronousProcess::locateBinary(searchPath, QLatin1String("qmlviewer")); Utils::Environment environment = Utils::Environment::systemEnvironment(); - m_applicationLauncher.setEnvironment(environment.toStringList()); + m_applicationLauncher.setEnvironment(environment); } bool QmlJSPreviewRunner::isReady() const @@ -63,7 +64,7 @@ void QmlJSPreviewRunner::run(const QString &filename) QString errorMessage; if (!filename.isEmpty()) { m_applicationLauncher.start(ProjectExplorer::ApplicationLauncher::Gui, m_qmlViewerDefaultPath, - QStringList() << filename); + Utils::QtcProcess::quoteArg(filename)); } else { errorMessage = "No file specified."; diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp index 4c28260adc717a3fd15e0c64eabd6d09c5b37cd1..5a51a0cea3cd1c3725240429441cce5a24f9cb9e 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp @@ -43,6 +43,7 @@ #include <utils/debuggerlanguagechooser.h> #include <utils/detailswidget.h> #include <utils/qtcassert.h> +#include <utils/qtcprocess.h> #include <qt4projectmanager/qtversionmanager.h> #include <qt4projectmanager/qt4projectmanagerconstants.h> #include <qt4projectmanager/qmlobservertool.h> @@ -135,23 +136,20 @@ QString QmlProjectRunConfiguration::observerPath() const } } -QStringList QmlProjectRunConfiguration::viewerArguments() const +QString QmlProjectRunConfiguration::viewerArguments() const { - QStringList args; - // arguments in .user file - if (!m_qmlViewerArgs.isEmpty()) - args.append(m_qmlViewerArgs.split(QLatin1Char(' '))); + QString args = m_qmlViewerArgs; // arguments from .qmlproject file foreach (const QString &importPath, qmlTarget()->qmlProject()->importPaths()) { - args.append(QLatin1String("-I")); - args.append(importPath); + Utils::QtcProcess::addArg(&args, "-I"); + Utils::QtcProcess::addArg(&args, importPath); } - const QString s = mainScript(); - if (! s.isEmpty()) - args.append(s); + const QString &s = mainScript(); + if (!s.isEmpty()) + Utils::QtcProcess::addArg(&args, s); return args; } diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h index 5942a76c0a8e027ac4fdc8bfacd395590dc73426..74d61dce6efd3e9a694bab0ef2c0dd1915f732d6 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h +++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h @@ -75,7 +75,7 @@ public: QString viewerPath() const; QString observerPath() const; - QStringList viewerArguments() const; + QString viewerArguments() const; QString workingDirectory() const; int qtVersionId() const; Qt4ProjectManager::QtVersion *qtVersion() const; diff --git a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp index 861c58537c57d39c6b7a6bb48e74e7022e16c045..cfaf92e77d1c6b64f7c55bbb2a76107fef2b52b5 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp @@ -37,6 +37,7 @@ #include <qt4projectmanager/qtversionmanager.h> #include <utils/environment.h> #include <utils/qtcassert.h> +#include <utils/qtcprocess.h> #include <debugger/debuggerrunner.h> #include <debugger/debuggerplugin.h> @@ -64,7 +65,9 @@ QmlRunControl::QmlRunControl(QmlProjectRunConfiguration *runConfiguration, QStri : RunControl(runConfiguration, mode) { if (Qt4ProjectManager::QtVersion *qtVersion = runConfiguration->qtVersion()) - m_applicationLauncher.setEnvironment(qtVersion->qmlToolsEnvironment().toStringList()); + m_applicationLauncher.setEnvironment(qtVersion->qmlToolsEnvironment()); + else + m_applicationLauncher.setEnvironment(Utils::Environment::systemEnvironment()); m_applicationLauncher.setWorkingDirectory(runConfiguration->workingDirectory()); if (mode == ProjectExplorer::Constants::RUNMODE) { @@ -96,7 +99,7 @@ void QmlRunControl::start() emit started(); emit appendMessage(this, tr("Starting %1 %2").arg(QDir::toNativeSeparators(m_executable), - m_commandLineArguments.join(QLatin1String(" "))), false); + m_commandLineArguments), false); } RunControl::StopResult QmlRunControl::stop() @@ -200,10 +203,11 @@ ProjectExplorer::RunControl *QmlRunControlFactory::createDebugRunControl(QmlProj params.qmlServerAddress = "127.0.0.1"; params.qmlServerPort = runConfig->qmlDebugServerPort(); params.processArgs = runConfig->viewerArguments(); - params.processArgs.append(QLatin1String("-qmljsdebugger=port:") + QString::number(runConfig->qmlDebugServerPort())); + Utils::QtcProcess::addArg(¶ms.processArgs, + QLatin1String("-qmljsdebugger=port:") + QString::number(runConfig->qmlDebugServerPort())); params.workingDirectory = runConfig->workingDirectory(); if (Qt4ProjectManager::QtVersion *qtVersion = runConfig->qtVersion()) - params.environment = qtVersion->qmlToolsEnvironment().toStringList(); + params.environment = qtVersion->qmlToolsEnvironment(); params.displayName = runConfig->displayName(); if (params.executable.isEmpty()) { diff --git a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.h b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.h index 9254becabc0a5edce1825e174119b99828c636b6..3d6c58588bd926278018ade61472decf71b71490 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.h +++ b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.h @@ -61,7 +61,7 @@ private: ProjectExplorer::ApplicationLauncher m_applicationLauncher; QString m_executable; - QStringList m_commandLineArguments; + QString m_commandLineArguments; }; class QmlRunControlFactory : public ProjectExplorer::IRunControlFactory { diff --git a/src/plugins/qt4projectmanager/makestep.cpp b/src/plugins/qt4projectmanager/makestep.cpp index 400b6ee6b75cbc8e888dc0cface9e4c900471cc9..7a34273cd0801672c860c469fd95df1ae29458d9 100644 --- a/src/plugins/qt4projectmanager/makestep.cpp +++ b/src/plugins/qt4projectmanager/makestep.cpp @@ -43,6 +43,7 @@ #include <projectexplorer/gnumakeparser.h> #include <projectexplorer/projectexplorer.h> #include <extensionsystem/pluginmanager.h> +#include <utils/qtcprocess.h> #include <QtCore/QDir> #include <QtCore/QFileInfo> @@ -113,7 +114,7 @@ QVariantMap MakeStep::toMap() const bool MakeStep::fromMap(const QVariantMap &map) { m_makeCmd = map.value(QLatin1String(MAKE_COMMAND_KEY)).toString(); - m_userArgs = map.value(QLatin1String(MAKE_ARGUMENTS_KEY)).toStringList(); + m_userArgs = map.value(QLatin1String(MAKE_ARGUMENTS_KEY)).toString(); m_clean = map.value(QLatin1String(CLEAN_KEY)).toBool(); return ProjectExplorer::AbstractProcessStep::fromMap(map); @@ -150,22 +151,26 @@ bool MakeStep::init() // we should stop the clean queue // That is mostly so that rebuild works on a already clean project setIgnoreReturnValue(m_clean); - QStringList args; + + QString args; ProjectExplorer::ToolChain *toolchain = bc->toolChain(); if (bc->subNodeBuild()){ if(!bc->subNodeBuild()->makefile().isEmpty()) { - args << "-f" << bc->subNodeBuild()->makefile(); + Utils::QtcProcess::addArg(&args, QLatin1String("-f")); + Utils::QtcProcess::addArg(&args, bc->subNodeBuild()->makefile()); } } else if (!bc->makefile().isEmpty()) { - args << "-f" << bc->makefile(); + Utils::QtcProcess::addArg(&args, QLatin1String("-f")); + Utils::QtcProcess::addArg(&args, bc->makefile()); } - args.append(m_userArgs); + Utils::QtcProcess::addArgs(&args, m_userArgs); + if (!m_clean) { if (!bc->defaultMakeTarget().isEmpty()) - args << bc->defaultMakeTarget(); + Utils::QtcProcess::addArg(&args, bc->defaultMakeTarget()); } // -w option enables "Enter"/"Leaving directory" messages, which we need for detecting the // absolute file path @@ -177,7 +182,7 @@ bool MakeStep::init() if (toolchain->type() != ProjectExplorer::ToolChain_MSVC && toolchain->type() != ProjectExplorer::ToolChain_WINCE) { if (m_makeCmd.isEmpty()) - args << "-w"; + Utils::QtcProcess::addArg(&args, QLatin1String("-w")); } } @@ -235,12 +240,12 @@ ProjectExplorer::BuildStepConfigWidget *MakeStep::createConfigWidget() return new MakeStepConfigWidget(this); } -QStringList MakeStep::userArguments() +QString MakeStep::userArguments() { return m_userArgs; } -void MakeStep::setUserArguments(const QStringList &arguments) +void MakeStep::setUserArguments(const QString &arguments) { m_userArgs = arguments; emit userArgumentsChanged(); @@ -314,16 +319,16 @@ void MakeStepConfigWidget::updateDetails() // FIXME doing this without the user having a way to override this is rather bad // so we only do it for unix and if the user didn't override the make command // but for now this is the least invasive change - QStringList args = m_makeStep->userArguments(); + QString args = m_makeStep->userArguments(); ProjectExplorer::ToolChainType t = ProjectExplorer::ToolChain_UNKNOWN; ProjectExplorer::ToolChain *toolChain = bc->toolChain(); if (toolChain) t = toolChain->type(); if (t != ProjectExplorer::ToolChain_MSVC && t != ProjectExplorer::ToolChain_WINCE) { if (m_makeStep->m_makeCmd.isEmpty()) - args << "-w"; + Utils::QtcProcess::addArg(&args, QLatin1String("-w")); } - m_summaryText = tr("<b>Make:</b> %1 %2 in %3").arg(QFileInfo(makeCmd).fileName(), args.join(" "), + m_summaryText = tr("<b>Make:</b> %1 %2 in %3").arg(QFileInfo(makeCmd).fileName(), args, QDir::toNativeSeparators(workingDirectory)); emit updateSummary(); } @@ -342,8 +347,7 @@ void MakeStepConfigWidget::userArgumentsChanged() { if (m_ignoreChange) return; - const QStringList &makeArguments = m_makeStep->userArguments(); - m_ui->makeArgumentsLineEdit->setText(Utils::Environment::joinArgumentList(makeArguments)); + m_ui->makeArgumentsLineEdit->setText(m_makeStep->userArguments()); updateDetails(); } @@ -354,8 +358,7 @@ void MakeStepConfigWidget::init() const QString &makeCmd = m_makeStep->m_makeCmd; m_ui->makePathChooser->setPath(makeCmd); - const QStringList &makeArguments = m_makeStep->userArguments(); - m_ui->makeArgumentsLineEdit->setText(Utils::Environment::joinArgumentList(makeArguments)); + m_ui->makeArgumentsLineEdit->setText(m_makeStep->userArguments()); updateDetails(); } @@ -368,8 +371,7 @@ void MakeStepConfigWidget::makeEdited() void MakeStepConfigWidget::makeArgumentsLineEdited() { m_ignoreChange = true; - m_makeStep->setUserArguments( - Utils::Environment::parseCombinedArgString(m_ui->makeArgumentsLineEdit->text())); + m_makeStep->setUserArguments(m_ui->makeArgumentsLineEdit->text()); m_ignoreChange = false; updateDetails(); } diff --git a/src/plugins/qt4projectmanager/makestep.h b/src/plugins/qt4projectmanager/makestep.h index ee650b413656ad55854f17821322fb563fdc2bb8..0858e55fd9a72902d6fc72ee890ca51c2b91d071 100644 --- a/src/plugins/qt4projectmanager/makestep.h +++ b/src/plugins/qt4projectmanager/makestep.h @@ -91,8 +91,8 @@ public: virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget(); virtual bool immutable() const; - QStringList userArguments(); - void setUserArguments(const QStringList &arguments); + QString userArguments(); + void setUserArguments(const QString &arguments); void setClean(bool clean); QVariantMap toMap() const; @@ -108,7 +108,7 @@ protected: private: void ctor(); bool m_clean; - QStringList m_userArgs; + QString m_userArgs; QString m_makeCmd; ProjectExplorer::GnuMakeParser * m_gnuMakeParser; }; diff --git a/src/plugins/qt4projectmanager/qmakestep.cpp b/src/plugins/qt4projectmanager/qmakestep.cpp index 63753bb4267ebc0ce31edb1065d9e5a448f9f192..82a0ddc2814500b9683f5df2de97f919e441b8d8 100644 --- a/src/plugins/qt4projectmanager/qmakestep.cpp +++ b/src/plugins/qt4projectmanager/qmakestep.cpp @@ -42,6 +42,7 @@ #include <coreplugin/icore.h> #include <utils/qtcassert.h> +#include <utils/qtcprocess.h> #include <QtCore/QDir> #include <QtCore/QFile> @@ -100,29 +101,34 @@ Qt4BuildConfiguration *QMakeStep::qt4BuildConfiguration() const /// config arguemnts /// moreArguments /// user arguments -QStringList QMakeStep::allArguments() +QString QMakeStep::allArguments(bool shorted) { - QStringList additonalArguments = m_userArgs; + QString additonalArguments = m_userArgs; Qt4BuildConfiguration *bc = qt4BuildConfiguration(); QStringList arguments; if (bc->subNodeBuild()) arguments << QDir::toNativeSeparators(bc->subNodeBuild()->path()); + else if (shorted) + arguments << QDir::toNativeSeparators(QFileInfo( + buildConfiguration()->target()->project()->file()->fileName()).fileName()); else arguments << QDir::toNativeSeparators(buildConfiguration()->target()->project()->file()->fileName()); arguments << "-r"; - if (!additonalArguments.contains("-spec")) - arguments << "-spec" << bc->qtVersion()->mkspec(); + for (Utils::QtcProcess::ArgIterator ait(&additonalArguments); ait.next(); ) + if (ait.value() == QLatin1String("-spec")) + goto haveSpec; + arguments << "-spec" << bc->qtVersion()->mkspec(); + haveSpec: // Find out what flags we pass on to qmake arguments << bc->configCommandLineArguments(); - if (!additonalArguments.isEmpty()) - arguments << additonalArguments; - arguments << moreArguments(); - return arguments; + QString args = Utils::QtcProcess::joinArgs(arguments); + Utils::QtcProcess::addArgs(&args, additonalArguments); + return args; } /// @@ -164,7 +170,7 @@ bool QMakeStep::init() Qt4BuildConfiguration *qt4bc = qt4BuildConfiguration(); const QtVersion *qtVersion = qt4bc->qtVersion(); - QStringList args = allArguments(); + QString args = allArguments(); QString workingDirectory; if (qt4bc->subNodeBuild()) @@ -286,7 +292,7 @@ bool QMakeStep::processSucceeded(int exitCode, QProcess::ExitStatus status) return result; } -void QMakeStep::setUserArguments(const QStringList &arguments) +void QMakeStep::setUserArguments(const QString &arguments) { if (m_userArgs == arguments) return; @@ -301,14 +307,13 @@ void QMakeStep::setUserArguments(const QStringList &arguments) QStringList QMakeStep::parserArguments() { QStringList result; - foreach (const QString &str, allArguments()) { - if (str.contains("=")) - result << str; - } + for (Utils::QtcProcess::ConstArgIterator ait(allArguments()); ait.next(); ) + if (ait.value().contains(QLatin1Char('='))) + result << ait.value(); return result; } -QStringList QMakeStep::userArguments() +QString QMakeStep::userArguments() { return m_userArgs; } @@ -322,7 +327,7 @@ QVariantMap QMakeStep::toMap() const bool QMakeStep::fromMap(const QVariantMap &map) { - m_userArgs = map.value(QLatin1String(QMAKE_ARGUMENTS_KEY)).toStringList(); + m_userArgs = map.value(QLatin1String(QMAKE_ARGUMENTS_KEY)).toString(); return BuildStep::fromMap(map); } @@ -349,8 +354,7 @@ QMakeStepConfigWidget::QMakeStepConfigWidget(QMakeStep *step) void QMakeStepConfigWidget::init() { - QString qmakeArgs = Utils::Environment::joinArgumentList(m_step->userArguments()); - m_ui.qmakeAdditonalArgumentsLineEdit->setText(qmakeArgs); + m_ui.qmakeAdditonalArgumentsLineEdit->setText(m_step->userArguments()); qmakeBuildConfigChanged(); @@ -393,8 +397,7 @@ void QMakeStepConfigWidget::userArgumentsChanged() { if (m_ignoreChange) return; - QString qmakeArgs = Utils::Environment::joinArgumentList(m_step->userArguments()); - m_ui.qmakeAdditonalArgumentsLineEdit->setText(qmakeArgs); + m_ui.qmakeAdditonalArgumentsLineEdit->setText(m_step->userArguments()); updateSummaryLabel(); updateEffectiveQMakeCall(); } @@ -402,8 +405,7 @@ void QMakeStepConfigWidget::userArgumentsChanged() void QMakeStepConfigWidget::qmakeArgumentsLineEdited() { m_ignoreChange = true; - m_step->setUserArguments( - Utils::Environment::parseCombinedArgString(m_ui.qmakeAdditonalArgumentsLineEdit->text())); + m_step->setUserArguments(m_ui.qmakeAdditonalArgumentsLineEdit->text()); m_ignoreChange = false; updateSummaryLabel(); @@ -446,16 +448,11 @@ void QMakeStepConfigWidget::updateSummaryLabel() return; } - QStringList args = m_step->allArguments(); // We don't want the full path to the .pro file - const QString projectFileName = m_step->buildConfiguration()->target()->project()->file()->fileName(); - int index = args.indexOf(projectFileName); - if (index != -1) - args[index] = QFileInfo(projectFileName).fileName(); - + QString args = m_step->allArguments(true); // And we only use the .pro filename not the full path QString program = QFileInfo(qtVersion->qmakeCommand()).fileName(); - m_summaryText = tr("<b>qmake:</b> %1 %2").arg(program, args.join(QString(QLatin1Char(' ')))); + m_summaryText = tr("<b>qmake:</b> %1 %2").arg(program, args); emit updateSummary(); } @@ -465,7 +462,7 @@ void QMakeStepConfigWidget::updateEffectiveQMakeCall() Qt4BuildConfiguration *qt4bc = m_step->qt4BuildConfiguration(); const QtVersion *qtVersion = qt4bc->qtVersion(); QString program = QFileInfo(qtVersion->qmakeCommand()).fileName(); - m_ui.qmakeArgumentsEdit->setPlainText(program + QLatin1Char(' ') + Utils::Environment::joinArgumentList(m_step->allArguments())); + m_ui.qmakeArgumentsEdit->setPlainText(program + QLatin1Char(' ') + m_step->allArguments()); } //// diff --git a/src/plugins/qt4projectmanager/qmakestep.h b/src/plugins/qt4projectmanager/qmakestep.h index 0f3c00c3ee9c8564923bafcae128715a9145bc59..09befadf7384eda863693de24d89f2484fc8345c 100644 --- a/src/plugins/qt4projectmanager/qmakestep.h +++ b/src/plugins/qt4projectmanager/qmakestep.h @@ -86,11 +86,11 @@ public: bool forced(); // TODO clean up those functions - QStringList allArguments(); + QString allArguments(bool shorted = false); QStringList moreArguments(); QStringList parserArguments(); - QStringList userArguments(); - void setUserArguments(const QStringList &arguments); + QString userArguments(); + void setUserArguments(const QString &arguments); QVariantMap toMap() const; @@ -112,7 +112,7 @@ private: QStringList m_lastEnv; bool m_forced; bool m_needToRunQMake; // set in init(), read in run() - QStringList m_userArgs; + QString m_userArgs; bool m_scriptTemplate; QList<ProjectExplorer::Task> m_tasks; }; diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.cpp index 4b2ac4e5b92e37d19b8c571e6c6a7e39a9e34355..2c2e6156a89e5576589e4e3a708c6de420b23c3c 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.cpp +++ b/src/plugins/qt4projectmanager/qt-maemo/maemodebugsupport.cpp @@ -270,7 +270,7 @@ void MaemoDebugSupport::startDebugging() const QString cmdPrefix = MaemoGlobal::remoteCommandPrefix(remoteExe); const QString env = environment(m_debuggingType, m_runner->userEnvChanges()); - const QString args = m_runner->arguments().join(QLatin1String(" ")); + const QString args = m_runner->arguments(); const QString remoteCommandLine = m_debuggingType == MaemoRunConfiguration::DebugQmlOnly ? QString::fromLocal8Bit("%1 %2 %3 %4").arg(cmdPrefix).arg(env) diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp index 39e74db339065fdd2aeff5bdae9c67fc61c87242..fe118baee0f14d6937b985f0ac4dc7d18ba700b7 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.cpp @@ -49,6 +49,7 @@ #include <qt4projectmanager/qt4project.h> #include <utils/qtcassert.h> +#include <utils/qtcprocess.h> #include <QtCore/QStringBuilder> @@ -185,7 +186,7 @@ bool MaemoRunConfiguration::fromMap(const QVariantMap &map) if (!RunConfiguration::fromMap(map)) return false; - m_arguments = map.value(ArgumentsKey).toStringList(); + m_arguments = map.value(ArgumentsKey).toString(); const QDir dir = QDir(target()->project()->projectDirectory()); m_proFilePath = dir.filePath(map.value(ProFileKey).toString()); m_useRemoteGdb = map.value(UseRemoteGdbKey, DefaultUseRemoteGdbValue).toBool(); @@ -262,7 +263,7 @@ const QString MaemoRunConfiguration::targetRoot() const return QString(); } -const QStringList MaemoRunConfiguration::arguments() const +const QString MaemoRunConfiguration::arguments() const { return m_arguments; } @@ -334,7 +335,7 @@ bool MaemoRunConfiguration::useRemoteGdb() const return m_useRemoteGdb && toolchain()->allowsRemoteMounts(); } -void MaemoRunConfiguration::setArguments(const QStringList &args) +void MaemoRunConfiguration::setArguments(const QString &args) { m_arguments = args; } diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h index 0288b08a82bd5ac79185588c06cbbad475d27e88..883fef516a619a73b1478d0abcf750dd1809d109 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h +++ b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfiguration.h @@ -92,8 +92,8 @@ public: QString remoteExecutableFilePath() const; const QString sysRoot() const; const QString targetRoot() const; - const QStringList arguments() const; - void setArguments(const QStringList &args); + const QString arguments() const; + void setArguments(const QString &args); MaemoDeviceConfig deviceConfig() const; MaemoPortList freePorts() const; bool useRemoteGdb() const; @@ -149,7 +149,7 @@ private: QString m_proFilePath; mutable QString m_gdbPath; MaemoRemoteMountsModel *m_remoteMounts; - QStringList m_arguments; + QString m_arguments; bool m_useRemoteGdb; BaseEnvironmentBase m_baseEnvironmentBase; diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfigurationwidget.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfigurationwidget.cpp index d2a8799e924f277823e66f65d7e8eea890b90ba1..1b1f6eea491ea3adf6bd9e0cc5e179aabaabdf66 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemorunconfigurationwidget.cpp +++ b/src/plugins/qt4projectmanager/qt-maemo/maemorunconfigurationwidget.cpp @@ -137,7 +137,7 @@ void MaemoRunConfigurationWidget::addGenericWidgets(QVBoxLayout *mainLayout) formLayout->addRow(tr("Executable on host:"), m_localExecutableLabel); m_remoteExecutableLabel = new QLabel; formLayout->addRow(tr("Executable on device:"), m_remoteExecutableLabel); - m_argsLineEdit = new QLineEdit(m_runConfiguration->arguments().join(" ")); + m_argsLineEdit = new QLineEdit(m_runConfiguration->arguments()); formLayout->addRow(tr("Arguments:"), m_argsLineEdit); QHBoxLayout * const debugButtonsLayout = new QHBoxLayout; @@ -293,7 +293,7 @@ void MaemoRunConfigurationWidget::addEnvironmentWidgets(QVBoxLayout *mainLayout) void MaemoRunConfigurationWidget::argumentsEdited(const QString &text) { - m_runConfiguration->setArguments(text.split(' ', QString::SkipEmptyParts)); + m_runConfiguration->setArguments(text); } void MaemoRunConfigurationWidget::updateTargetInformation() diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.cpp index aabc0c2c249e2ed2f392cece7de09715b30db369..388450e41c7c536a3188ba9a796a5507cd11842d 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.cpp +++ b/src/plugins/qt4projectmanager/qt-maemo/maemoruncontrol.cpp @@ -104,7 +104,7 @@ void MaemoRunControl::startExecution() .arg(MaemoGlobal::remoteCommandPrefix(m_runner->remoteExecutable())) .arg(MaemoGlobal::remoteEnvironment(m_runner->userEnvChanges())) .arg(m_runner->remoteExecutable()) - .arg(m_runner->arguments().join(QLatin1String(" "))).toUtf8()); + .arg(m_runner->arguments()).toUtf8()); } void MaemoRunControl::handleRemoteProcessFinished(qint64 exitCode) diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemosshrunner.h b/src/plugins/qt4projectmanager/qt-maemo/maemosshrunner.h index 94828e5385d9f8ea297401278faa64ed4511811f..dba27d2e18ab496dfb254501cd66744043d4f431 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemosshrunner.h +++ b/src/plugins/qt4projectmanager/qt-maemo/maemosshrunner.h @@ -74,7 +74,7 @@ public: MaemoPortList *freePorts() { return &m_freePorts; } MaemoDeviceConfig deviceConfig() const { return m_devConfig; } QString remoteExecutable() const { return m_remoteExecutable; } - QStringList arguments() const { return m_appArguments; } + QString arguments() const { return m_appArguments; } QList<Utils::EnvironmentItem> userEnvChanges() const { return m_userEnvChanges; } static const qint64 InvalidExitCode; @@ -118,7 +118,7 @@ private: MaemoUsedPortsGatherer * const m_portsGatherer; const MaemoDeviceConfig m_devConfig; const QString m_remoteExecutable; - const QStringList m_appArguments; + const QString m_appArguments; const QList<Utils::EnvironmentItem> m_userEnvChanges; const MaemoPortList m_initialFreePorts; QList<MaemoMountSpecification> m_mountSpecs; diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp index 8958d5686e0ef04b66e0151c3a66312320c63352..128a96347e9d287647711bb450405eba1281c9b0 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp @@ -225,7 +225,7 @@ bool S60DeviceRunConfiguration::fromMap(const QVariantMap &map) const QDir projectDir = QDir(target()->project()->projectDirectory()); m_proFilePath = projectDir.filePath(map.value(QLatin1String(PRO_FILE_KEY)).toString()); - m_commandLineArguments = map.value(QLatin1String(COMMAND_LINE_ARGUMENTS_KEY)).toStringList(); + m_commandLineArguments = map.value(QLatin1String(COMMAND_LINE_ARGUMENTS_KEY)).toString(); if (m_proFilePath.isEmpty()) return false; @@ -368,12 +368,12 @@ QString S60DeviceRunConfiguration::projectFilePath() const return m_proFilePath; } -QStringList S60DeviceRunConfiguration::commandLineArguments() const +QString S60DeviceRunConfiguration::commandLineArguments() const { return m_commandLineArguments; } -void S60DeviceRunConfiguration::setCommandLineArguments(const QStringList &args) +void S60DeviceRunConfiguration::setCommandLineArguments(const QString &args) { m_commandLineArguments = args; } diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h index bee69b71ecddee6e758e63cd4bec2aba162b51c3..8e0b479febd8f8e272da3d545933920a4f4e1ad5 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h @@ -77,8 +77,8 @@ public: ProjectExplorer::OutputFormatter *createOutputFormatter() const; - QStringList commandLineArguments() const; - void setCommandLineArguments(const QStringList &args); + QString commandLineArguments() const; + void setCommandLineArguments(const QString &args); QString projectFilePath() const; @@ -112,7 +112,7 @@ private: void handleParserState(bool sucess); QString m_proFilePath; - QStringList m_commandLineArguments; + QString m_commandLineArguments; bool m_validParse; }; @@ -184,7 +184,7 @@ private: QString m_serialPortName; QString m_serialPortFriendlyName; QString m_targetName; - QStringList m_commandLineArguments; + QString m_commandLineArguments; QString m_executableFileName; QString m_qtDir; QString m_qtBinPath; diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp index 339343dfac8e380139bf80ee4598a549ae15803c..7aa0c2d70509f1a7be432da0f91191e6510f4364 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp @@ -46,7 +46,7 @@ S60DeviceRunConfigurationWidget::S60DeviceRunConfigurationWidget( : QWidget(parent), m_runConfiguration(runConfiguration), m_detailsWidget(new Utils::DetailsWidget), - m_argumentsLineEdit(new QLineEdit(m_runConfiguration->commandLineArguments().join(QString(QLatin1Char(' '))))) + m_argumentsLineEdit(new QLineEdit(m_runConfiguration->commandLineArguments())) { m_detailsWidget->setState(Utils::DetailsWidget::NoSummary); QVBoxLayout *mainBoxLayout = new QVBoxLayout(); @@ -76,13 +76,7 @@ S60DeviceRunConfigurationWidget::S60DeviceRunConfigurationWidget( void S60DeviceRunConfigurationWidget::argumentsEdited(const QString &text) { - const QString trimmed = text.trimmed(); - if (trimmed.isEmpty()) { - m_runConfiguration->setCommandLineArguments(QStringList()); - } else { - m_runConfiguration->setCommandLineArguments(trimmed.split(QLatin1Char(' '), - QString::SkipEmptyParts)); - } + m_runConfiguration->setCommandLineArguments(text.trimmed()); } void S60DeviceRunConfigurationWidget::runConfigurationEnabledChange(bool enabled) diff --git a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp index d01a3686537246e42178be9314a4bde2ef08b4d6..2fb2d1c6fe1989b081a23cd80c04e81ee342c004 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp @@ -327,7 +327,7 @@ S60EmulatorRunControl::S60EmulatorRunControl(S60EmulatorRunConfiguration *runCon // stuff like the EPOCROOT and EPOCDEVICE env variable Utils::Environment env = Utils::Environment::systemEnvironment(); runConfiguration->qt4Target()->activeBuildConfiguration()->toolChain()->addToEnvironment(env); - m_applicationLauncher.setEnvironment(env.toStringList()); + m_applicationLauncher.setEnvironment(env); m_executable = runConfiguration->executable(); connect(&m_applicationLauncher, SIGNAL(applicationError(QString)), @@ -342,7 +342,7 @@ S60EmulatorRunControl::S60EmulatorRunControl(S60EmulatorRunConfiguration *runCon void S60EmulatorRunControl::start() { - m_applicationLauncher.start(ApplicationLauncher::Gui, m_executable, QStringList()); + m_applicationLauncher.start(ApplicationLauncher::Gui, m_executable, QString()); emit started(); emit appendMessage(this, tr("Starting %1...").arg(QDir::toNativeSeparators(m_executable)), false); diff --git a/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp b/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp index d19abc99fa43c92d26c6b8adc603fc8a89bd57b3..54cb7f82946122aa443a4a02ba8ec5351faa9ff5 100644 --- a/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt4buildconfiguration.cpp @@ -37,6 +37,7 @@ #include "makestep.h" #include <utils/qtcassert.h> +#include <utils/qtcprocess.h> #include <limits> #include <projectexplorer/buildsteplist.h> #include <projectexplorer/projectexplorerconstants.h> @@ -494,7 +495,7 @@ bool Qt4BuildConfiguration::compareToImportFrom(const QString &makefile) QtVersion *version = qtVersion(); if (version->qmakeCommand() == qmakePath) { // same qtversion - QPair<QtVersion::QmakeBuildConfigs, QStringList> result = + QPair<QtVersion::QmakeBuildConfigs, QString> result = QtVersionManager::scanMakeFile(makefile, version->defaultBuildConfig()); if (qmakeBuildConfiguration() == result.first) { // The qmake Build Configuration are the same, @@ -502,18 +503,18 @@ bool Qt4BuildConfiguration::compareToImportFrom(const QString &makefile) // we have to compare without the spec/platform cmd argument // and compare that on its own QString workingDirectory = QFileInfo(makefile).absolutePath(); - QString actualSpec = extractSpecFromArgumentList(qs->userArguments(), workingDirectory, version); + QString userArgs = qs->userArguments(); + QStringList actualArgs; + QString actualSpec = extractSpecFromArguments(&userArgs, workingDirectory, version, &actualArgs); if (actualSpec.isEmpty()) { // Easy one: the user has chosen not to override the settings actualSpec = version->mkspec(); } + actualArgs += qs->moreArguments(); - - QString parsedSpec = extractSpecFromArgumentList(result.second, workingDirectory, version); - QStringList actualArgs = qs->moreArguments(); - actualArgs << qs->userArguments(); - actualArgs = removeSpecFromArgumentList(actualArgs); - QStringList parsedArgs = removeSpecFromArgumentList(result.second); + QString qmakeArgs = result.second; + QStringList parsedArgs; + QString parsedSpec = extractSpecFromArguments(&qmakeArgs, workingDirectory, version, &parsedArgs); if (debug) { qDebug()<<"Actual args:"<<actualArgs; @@ -558,59 +559,53 @@ bool Qt4BuildConfiguration::compareToImportFrom(const QString &makefile) return false; } -QStringList Qt4BuildConfiguration::removeQMLInspectorFromArgumentList(const QStringList &old) +void Qt4BuildConfiguration::removeQMLInspectorFromArguments(QString *args) { - QStringList result; - foreach (const QString &str, old) - if (!str.startsWith(QLatin1String(Constants::QMAKEVAR_QMLJSDEBUGGER_PATH))) - result << str; - return result; + for (Utils::QtcProcess::ArgIterator ait(args); ait.next(); ) + if (ait.value().startsWith(QLatin1String(Constants::QMAKEVAR_QMLJSDEBUGGER_PATH))) + ait.deleteArg(); } -// We match -spec and -platfrom separetly -// We ignore -cache, because qmake contained a bug that it didn't -// mention the -cache in the Makefile -// That means changing the -cache option in the additional arguments -// does not automatically rerun qmake. Alas, we could try more -// intelligent matching for -cache, but i guess people rarely -// do use that. - -QStringList Qt4BuildConfiguration::removeSpecFromArgumentList(const QStringList &old) +QString Qt4BuildConfiguration::extractSpecFromArguments(QString *args, + const QString &directory, const QtVersion *version, + QStringList *outArgs) { - if (!old.contains("-spec") && !old.contains("-platform") && !old.contains("-cache")) - return old; - QStringList newList; + QString parsedSpec; + bool ignoreNext = false; - foreach(const QString &item, old) { + bool nextIsSpec = false; + for (Utils::QtcProcess::ArgIterator ait(args); ait.next(); ) { if (ignoreNext) { ignoreNext = false; - } else if (item == "-spec" || item == "-platform" || item == "-cache") { + ait.deleteArg(); + } else if (nextIsSpec) { + nextIsSpec = false; + parsedSpec = QDir::cleanPath(ait.value()); + ait.deleteArg(); + } else if (ait.value() == QLatin1String("-spec") || ait.value() == QLatin1String("-platform")) { + nextIsSpec = true; + ait.deleteArg(); + } else if (ait.value() == QLatin1String("-cache")) { + // We ignore -cache, because qmake contained a bug that it didn't + // mention the -cache in the Makefile. + // That means changing the -cache option in the additional arguments + // does not automatically rerun qmake. Alas, we could try more + // intelligent matching for -cache, but i guess people rarely + // do use that. ignoreNext = true; - } else { - newList << item; + ait.deleteArg(); + } else if (outArgs && ait.isSimple()) { + outArgs->append(ait.value()); } } - return newList; -} - -QString Qt4BuildConfiguration::extractSpecFromArgumentList(const QStringList &list, QString directory, QtVersion *version) -{ - int index = list.indexOf("-spec"); - if (index == -1) - index = list.indexOf("-platform"); - if (index == -1) - return QString(); - - ++index; - if (index >= list.length()) + if (parsedSpec.isEmpty()) return QString(); QString baseMkspecDir = version->versionInfo().value("QMAKE_MKSPECS"); if (baseMkspecDir.isEmpty()) baseMkspecDir = version->versionInfo().value("QT_INSTALL_DATA") + "/mkspecs"; - QString parsedSpec = QDir::cleanPath(list.at(index)); #ifdef Q_OS_WIN baseMkspecDir = baseMkspecDir.toLower(); parsedSpec = parsedSpec.toLower(); @@ -753,12 +748,12 @@ BuildConfiguration *Qt4BuildConfigurationFactory::create(ProjectExplorer::Target qt4Target->addQt4BuildConfiguration(tr("%1 Debug").arg(buildConfigurationName), version, (version->defaultBuildConfig() | QtVersion::DebugBuild), - QStringList(), QString()); + QString(), QString()); BuildConfiguration *bc = qt4Target->addQt4BuildConfiguration(tr("%1 Release").arg(buildConfigurationName), version, (version->defaultBuildConfig() & ~QtVersion::DebugBuild), - QStringList(), QString()); + QString(), QString()); return bc; } diff --git a/src/plugins/qt4projectmanager/qt4buildconfiguration.h b/src/plugins/qt4projectmanager/qt4buildconfiguration.h index 956c95e73c26e0c8a5620c413efec14955f9b314..2a1940bbfecfa90de021c55e3ec7dd818fb6a03a 100644 --- a/src/plugins/qt4projectmanager/qt4buildconfiguration.h +++ b/src/plugins/qt4projectmanager/qt4buildconfiguration.h @@ -109,9 +109,10 @@ public: QString makefile() const; bool compareToImportFrom(const QString &makefile); - static QStringList removeQMLInspectorFromArgumentList(const QStringList &old); - static QStringList removeSpecFromArgumentList(const QStringList &old); - static QString extractSpecFromArgumentList(const QStringList &list, QString directory, QtVersion *version); + static void removeQMLInspectorFromArguments(QString *args); + static QString extractSpecFromArguments(QString *arguments, + const QString &directory, const QtVersion *version, + QStringList *outArgs = 0); QVariantMap toMap() const; diff --git a/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp b/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp index 081a20d2ae23d9fef29934febd0bd2717be64714..1056bf935d257e447bcf10375bc24dd9e74323cf 100644 --- a/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp +++ b/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp @@ -43,6 +43,7 @@ #include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/buildconfiguration.h> #include <utils/qtcassert.h> +#include <utils/qtcprocess.h> #include <extensionsystem/pluginmanager.h> #include <QtGui/QFileDialog> @@ -416,20 +417,22 @@ void Qt4ProjectConfigWidget::importLabelClicked() vm->addVersion(version); } - QPair<QtVersion::QmakeBuildConfigs, QStringList> result = + QPair<QtVersion::QmakeBuildConfigs, QString> result = QtVersionManager::scanMakeFile(directory, version->defaultBuildConfig()); QtVersion::QmakeBuildConfigs qmakeBuildConfig = result.first; - QStringList additionalArguments = Qt4BuildConfiguration::removeSpecFromArgumentList(result.second); - QString parsedSpec = Qt4BuildConfiguration::extractSpecFromArgumentList(result.second, directory, version); + + QString aa = result.second; + QString parsedSpec = Qt4BuildConfiguration::extractSpecFromArguments(&aa, directory, version); QString versionSpec = version->mkspec(); + QString additionalArguments; if (parsedSpec.isEmpty() || parsedSpec == versionSpec || parsedSpec == "default") { // using the default spec, don't modify additional arguments } else { - additionalArguments.prepend(parsedSpec); - additionalArguments.prepend("-spec"); + additionalArguments = "-spec " + Utils::QtcProcess::quoteArg(parsedSpec); } + Utils::QtcProcess::addArgs(&additionalArguments, aa); - additionalArguments = Qt4BuildConfiguration::removeQMLInspectorFromArgumentList(additionalArguments); + Qt4BuildConfiguration::removeQMLInspectorFromArguments(&additionalArguments); // So we got all the information now apply it... m_buildConfiguration->setQtVersion(version); @@ -443,16 +446,25 @@ void Qt4ProjectConfigWidget::importLabelClicked() // If we are switching to BuildAll we want "release" in there and no "debug" // or "debug" in there and no "release" // If we are switching to not BuildAl we want neither "release" nor "debug" in there - QStringList makeCmdArguments = makeStep->userArguments(); bool debug = qmakeBuildConfig & QtVersion::DebugBuild; - if (qmakeBuildConfig & QtVersion::BuildAll) { - makeCmdArguments.removeAll(debug ? "release" : "debug"); - if (!makeCmdArguments.contains(debug ? "debug" : "release")) - makeCmdArguments.append(debug ? "debug" : "release"); - } else { - makeCmdArguments.removeAll("debug"); - makeCmdArguments.removeAll("release"); + bool haveTag = !(qmakeBuildConfig & QtVersion::BuildAll); + QString makeCmdArguments = makeStep->userArguments(); + Utils::QtcProcess::ArgIterator ait(&makeCmdArguments); + while (ait.next()) { + if (ait.value() == QLatin1String("debug")) { + if (!haveTag && debug) + haveTag = true; + else + ait.deleteArg(); + } else if (ait.value() == QLatin1String("release")) { + if (!haveTag && !debug) + haveTag = true; + else + ait.deleteArg(); + } } + if (!haveTag) + ait.appendArg(QLatin1String(debug ? "debug" : "release")); makeStep->setUserArguments(makeCmdArguments); } } diff --git a/src/plugins/qt4projectmanager/qt4runconfiguration.cpp b/src/plugins/qt4projectmanager/qt4runconfiguration.cpp index 132d7be6bd4e2cd852ac24b2dc8a7b8847092c9a..5866a02e56d2ada224c85feae3b58bf6096d392b 100644 --- a/src/plugins/qt4projectmanager/qt4runconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt4runconfiguration.cpp @@ -47,6 +47,7 @@ #include <projectexplorer/environmenteditmodel.h> #include <projectexplorer/persistentsettings.h> #include <utils/qtcassert.h> +#include <utils/qtcprocess.h> #include <utils/pathchooser.h> #include <utils/detailswidget.h> #include <utils/debuggerlanguagechooser.h> @@ -220,7 +221,7 @@ Qt4RunConfigurationWidget::Qt4RunConfigurationWidget(Qt4RunConfiguration *qt4Run toplayout->addRow(tr("Executable:"), m_executableLineEdit); QLabel *argumentsLabel = new QLabel(tr("Arguments:"), this); - m_argumentsLineEdit = new QLineEdit(Utils::Environment::joinArgumentList(qt4RunConfiguration->baseCommandLineArguments()), this); + m_argumentsLineEdit = new QLineEdit(qt4RunConfiguration->commandLineArguments(), this); argumentsLabel->setBuddy(m_argumentsLineEdit); toplayout->addRow(argumentsLabel, m_argumentsLineEdit); @@ -326,7 +327,7 @@ Qt4RunConfigurationWidget::Qt4RunConfigurationWidget(Qt4RunConfiguration *qt4Run connect(qt4RunConfiguration, SIGNAL(baseWorkingDirectoryChanged(QString)), this, SLOT(workingDirectoryChanged(QString))); - connect(qt4RunConfiguration, SIGNAL(baseCommandLineArgumentsChanged(QString)), + connect(qt4RunConfiguration, SIGNAL(commandLineArgumentsChanged(QString)), this, SLOT(commandLineArgumentsChanged(QString))); connect(qt4RunConfiguration, SIGNAL(runModeChanged(ProjectExplorer::LocalApplicationRunConfiguration::RunMode)), this, SLOT(runModeChanged(ProjectExplorer::LocalApplicationRunConfiguration::RunMode))); @@ -424,7 +425,7 @@ void Qt4RunConfigurationWidget::workingDirectoryReseted() void Qt4RunConfigurationWidget::argumentsEdited(const QString &args) { m_ignoreChange = true; - m_qt4RunConfiguration->setBaseCommandLineArguments(args); + m_qt4RunConfiguration->setCommandLineArguments(args); m_ignoreChange = false; } @@ -514,7 +515,7 @@ QVariantMap Qt4RunConfiguration::toMap() const bool Qt4RunConfiguration::fromMap(const QVariantMap &map) { const QDir projectDir = QDir(target()->project()->projectDirectory()); - m_commandLineArguments = map.value(QLatin1String(COMMAND_LINE_ARGUMENTS_KEY)).toStringList(); + m_commandLineArguments = map.value(QLatin1String(COMMAND_LINE_ARGUMENTS_KEY)).toString(); m_proFilePath = projectDir.filePath(map.value(QLatin1String(PRO_FILE_KEY)).toString()); m_runMode = map.value(QLatin1String(USE_TERMINAL_KEY), false).toBool() ? Console : Gui; m_isUsingDyldImageSuffix = map.value(QLatin1String(USE_DYLD_IMAGE_SUFFIX_KEY), false).toBool(); @@ -573,12 +574,7 @@ QString Qt4RunConfiguration::baseWorkingDirectory() const return ti.workingDir; } -QStringList Qt4RunConfiguration::commandLineArguments() const -{ - return environment().expandVariables(baseCommandLineArguments()); -} - -QStringList Qt4RunConfiguration::baseCommandLineArguments() const +QString Qt4RunConfiguration::commandLineArguments() const { return m_commandLineArguments; } @@ -651,10 +647,10 @@ void Qt4RunConfiguration::setBaseWorkingDirectory(const QString &wd) emit baseWorkingDirectoryChanged(newWorkingDirectory); } -void Qt4RunConfiguration::setBaseCommandLineArguments(const QString &argumentsString) +void Qt4RunConfiguration::setCommandLineArguments(const QString &argumentsString) { - m_commandLineArguments = Utils::Environment::parseCombinedArgString(argumentsString); - emit baseCommandLineArgumentsChanged(argumentsString); + m_commandLineArguments = argumentsString; + emit commandLineArgumentsChanged(argumentsString); } void Qt4RunConfiguration::setRunMode(RunMode runMode) diff --git a/src/plugins/qt4projectmanager/qt4runconfiguration.h b/src/plugins/qt4projectmanager/qt4runconfiguration.h index 413f214253e9499dc77af2189d388bf3b844a726..3a57cc87f402d12565f998ac23a512c86b88a268 100644 --- a/src/plugins/qt4projectmanager/qt4runconfiguration.h +++ b/src/plugins/qt4projectmanager/qt4runconfiguration.h @@ -84,7 +84,7 @@ public: virtual QString executable() const; virtual RunMode runMode() const; virtual QString workingDirectory() const; - virtual QStringList commandLineArguments() const; + virtual QString commandLineArguments() const; virtual Utils::Environment environment() const; virtual QString dumperLibrary() const; virtual QStringList dumperLibraryLocations() const; @@ -101,7 +101,7 @@ public: ProjectExplorer::OutputFormatter *createOutputFormatter() const; signals: - void baseCommandLineArgumentsChanged(const QString&); + void commandLineArgumentsChanged(const QString&); void baseWorkingDirectoryChanged(const QString&); void runModeChanged(ProjectExplorer::LocalApplicationRunConfiguration::RunMode runMode); void usingDyldImageSuffixChanged(bool); @@ -124,8 +124,7 @@ private: void setRunMode(RunMode runMode); void setBaseWorkingDirectory(const QString &workingDirectory); QString baseWorkingDirectory() const; - void setBaseCommandLineArguments(const QString &argumentsString); - QStringList baseCommandLineArguments() const; + void setCommandLineArguments(const QString &argumentsString); enum BaseEnvironmentBase { CleanEnvironmentBase = 0, SystemEnvironmentBase = 1, BuildEnvironmentBase = 2 }; @@ -141,7 +140,7 @@ private: QList<Utils::EnvironmentItem> userEnvironmentChanges() const; void updateTarget(); - QStringList m_commandLineArguments; + QString m_commandLineArguments; QString m_proFilePath; // Full path to the Application Pro File // Cached startup sub project information diff --git a/src/plugins/qt4projectmanager/qt4target.cpp b/src/plugins/qt4projectmanager/qt4target.cpp index ccdbbc6b22822e9a7839d63fc9be77d4807ea9b7..e154d20ae7aa1a5f48306aa1e4c3321164a1e24c 100644 --- a/src/plugins/qt4projectmanager/qt4target.cpp +++ b/src/plugins/qt4projectmanager/qt4target.cpp @@ -274,7 +274,7 @@ Qt4Project *Qt4Target::qt4Project() const Qt4BuildConfiguration *Qt4Target::addQt4BuildConfiguration(QString displayName, QtVersion *qtversion, QtVersion::QmakeBuildConfigs qmakeBuildConfiguration, - QStringList additionalArguments, + QString additionalArguments, QString directory) { Q_ASSERT(qtversion); @@ -297,14 +297,14 @@ Qt4BuildConfiguration *Qt4Target::addQt4BuildConfiguration(QString displayName, MakeStep* cleanStep = new MakeStep(cleanSteps); cleanStep->setClean(true); - cleanStep->setUserArguments(QStringList() << "clean"); + cleanStep->setUserArguments("clean"); cleanSteps->insertStep(0, cleanStep); if (!additionalArguments.isEmpty()) qmakeStep->setUserArguments(additionalArguments); // set some options for qmake and make if (qmakeBuildConfiguration & QtVersion::BuildAll) // debug_and_release => explicit targets - makeStep->setUserArguments(QStringList() << (debug ? "debug" : "release")); + makeStep->setUserArguments(debug ? "debug" : "release"); bc->setQMakeBuildConfiguration(qmakeBuildConfiguration); diff --git a/src/plugins/qt4projectmanager/qt4target.h b/src/plugins/qt4projectmanager/qt4target.h index fa5c1cca857cc84292016ca99689f0b1a88bfde1..d6df4457c5a4e6401977b96944ace80c90a44fc7 100644 --- a/src/plugins/qt4projectmanager/qt4target.h +++ b/src/plugins/qt4projectmanager/qt4target.h @@ -47,12 +47,12 @@ class Qt4DeployConfigurationFactory; struct BuildConfigurationInfo { explicit BuildConfigurationInfo(QtVersion *v = 0, QtVersion::QmakeBuildConfigs bc = QtVersion::QmakeBuildConfig(0), - const QStringList &aa = QStringList(), const QString &d = QString()) : + const QString &aa = QString(), const QString &d = QString()) : version(v), buildConfig(bc), additionalArguments(aa), directory(d) { } QtVersion *version; QtVersion::QmakeBuildConfigs buildConfig; - QStringList additionalArguments; + QString additionalArguments; QString directory; }; @@ -71,7 +71,7 @@ public: Internal::Qt4BuildConfiguration *addQt4BuildConfiguration(QString displayName, QtVersion *qtversion, QtVersion::QmakeBuildConfigs qmakeBuildConfiguration, - QStringList additionalArguments, + QString additionalArguments, QString directory); void addRunConfigurationForPath(const QString &proFilePath); diff --git a/src/plugins/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp index ff9fb7ad4d0e26399691f88172f60f29e7f9bab2..16867f72787c5e3e64ec10949622e97c1777c74c 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.cpp +++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp @@ -49,6 +49,7 @@ #include <coreplugin/helpmanager.h> #include <extensionsystem/pluginmanager.h> #include <utils/qtcassert.h> +#include <utils/qtcprocess.h> #ifdef Q_OS_WIN # include <utils/winutils.h> #endif @@ -884,25 +885,21 @@ bool QtVersionManager::makefileIsFor(const QString &makefile, const QString &pro return srcFileInfo == proFileInfo; } -QPair<QtVersion::QmakeBuildConfigs, QStringList> QtVersionManager::scanMakeFile(const QString &makefile, QtVersion::QmakeBuildConfigs defaultBuildConfig) +QPair<QtVersion::QmakeBuildConfigs, QString> QtVersionManager::scanMakeFile(const QString &makefile, QtVersion::QmakeBuildConfigs defaultBuildConfig) { if (debug) qDebug()<<"ScanMakeFile, the gory details:"; QtVersion::QmakeBuildConfigs result = defaultBuildConfig; - QStringList result2; + QString result2; QString line = findQMakeLine(makefile, QLatin1String("# Command:")); if (!line.isEmpty()) { if (debug) qDebug()<<"Found line"<<line; line = trimLine(line); - QStringList parts = splitLine(line); - if (debug) - qDebug()<<"Split into"<<parts; QList<QMakeAssignment> assignments; QList<QMakeAssignment> afterAssignments; - QStringList additionalArguments; - parseParts(parts, &assignments, &afterAssignments, &additionalArguments); + parseArgs(line, &assignments, &afterAssignments, &result2); if (debug) { dumpQMakeAssignments(assignments); @@ -918,13 +915,12 @@ QPair<QtVersion::QmakeBuildConfigs, QStringList> QtVersionManager::scanMakeFile( if (debug) dumpQMakeAssignments(assignments); - result2.append(additionalArguments); foreach(const QMakeAssignment &qa, assignments) - result2.append(qa.variable + qa.op + qa.value); + Utils::QtcProcess::addArg(&result2, qa.variable + qa.op + qa.value); if (!afterAssignments.isEmpty()) { - result2.append("-after"); + Utils::QtcProcess::addArg(&result2, QLatin1String("-after")); foreach(const QMakeAssignment &qa, afterAssignments) - result2.append(qa.variable + qa.op + qa.value); + Utils::QtcProcess::addArg(&result2, qa.variable + qa.op + qa.value); } } @@ -965,55 +961,23 @@ QString QtVersionManager::trimLine(const QString line) return line.mid(firstSpace).trimmed(); } -QStringList QtVersionManager::splitLine(const QString &line) -{ - // Split on each " ", except on those which are escaped - // On Unix also remove all escaping - // On Windows also, but different escaping - bool escape = false; - QString currentWord; - QStringList results; - int length = line.length(); - for (int i=0; i<length; ++i) { -#ifdef Q_OS_WIN - if (line.at(i) == '"') { - escape = !escape; - } else if (escape || line.at(i) != ' ') { - currentWord += line.at(i); - } else { - results << currentWord; - currentWord.clear();; - } -#else - if (escape) { - currentWord += line.at(i); - escape = false; - } else if (line.at(i) == ' ') { - results << currentWord; - currentWord.clear(); - } else if (line.at(i) == '\\') { - escape = true; - } else { - currentWord += line.at(i); - } -#endif - } - return results; -} - -void QtVersionManager::parseParts(const QStringList &parts, QList<QMakeAssignment> *assignments, QList<QMakeAssignment> *afterAssignments, QStringList *additionalArguments) +void QtVersionManager::parseArgs(const QString &args, QList<QMakeAssignment> *assignments, QList<QMakeAssignment> *afterAssignments, QString *additionalArguments) { QRegExp regExp("([^\\s\\+-]*)\\s*(\\+=|=|-=|~=)(.*)"); bool after = false; bool ignoreNext = false; - foreach (const QString &part, parts) { + *additionalArguments = args; + Utils::QtcProcess::ArgIterator ait(additionalArguments); + while (ait.next()) { if (ignoreNext) { // Ignoring ignoreNext = false; - } else if (part == "-after") { + ait.deleteArg(); + } else if (ait.value() == QLatin1String("-after")) { after = true; - } else if(part.contains('=')) { - if (regExp.exactMatch(part)) { + ait.deleteArg(); + } else if (ait.value().contains(QLatin1Char('='))) { + if (regExp.exactMatch(ait.value())) { QMakeAssignment qa; qa.variable = regExp.cap(1); qa.op = regExp.cap(2); @@ -1025,21 +989,23 @@ void QtVersionManager::parseParts(const QStringList &parts, QList<QMakeAssignmen } else { qDebug()<<"regexp did not match"; } - } else if (part == "-o") { + ait.deleteArg(); + } else if (ait.value() == QLatin1String("-o")) { ignoreNext = true; - } else { - additionalArguments->append(part); - } - } + ait.deleteArg(); #if defined(Q_OS_WIN32) - additionalArguments->removeAll("-win32"); + } else if (ait.value() == QLatin1String("-win32")) { #elif defined(Q_OS_MAC) - additionalArguments->removeAll("-macx"); + } else if (ait.value() == QLatin1String("-macx")) { #elif defined(Q_OS_QNX6) - additionalArguments->removeAll("-qnx6"); + } else if (ait.value() == QLatin1String("-qnx6")) { #else - additionalArguments->removeAll("-unix"); + } else if (ait.value() == QLatin1String("-unix")) { #endif + ait.deleteArg(); + } + } + ait.deleteArg(); // The .pro file is always the last arg } /// This function extracts all the CONFIG+=debug, CONFIG+=release diff --git a/src/plugins/qt4projectmanager/qtversionmanager.h b/src/plugins/qt4projectmanager/qtversionmanager.h index 90d52c95ab22379aeab68e5fbb51bd89a026c0ba..9462a7ffb4dceafb31a053af7efdcccd3d71655f 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.h +++ b/src/plugins/qt4projectmanager/qtversionmanager.h @@ -265,9 +265,9 @@ public: // Static Methods static bool makefileIsFor(const QString &makefile, const QString &proFile); - static QPair<QtVersion::QmakeBuildConfigs, QStringList> scanMakeFile(const QString &makefile, - QtVersion::QmakeBuildConfigs defaultBuildConfig); - static QString findQMakeBinaryFromMakefile(const QString &makefile); + static QPair<QtVersion::QmakeBuildConfigs, QString> scanMakeFile(const QString &makefile, + QtVersion::QmakeBuildConfigs defaultBuildConfig); + static QString findQMakeBinaryFromMakefile(const QString &directory); bool isValidId(int id) const; signals: @@ -281,11 +281,10 @@ private: static bool equals(QtVersion *a, QtVersion *b); static QString findQMakeLine(const QString &directory, const QString &key); static QString trimLine(const QString line); - static QStringList splitLine(const QString &line); - static void parseParts(const QStringList &parts, - QList<QMakeAssignment> *assignments, - QList<QMakeAssignment> *afterAssignments, - QStringList *additionalArguments); + static void parseArgs(const QString &args, + QList<QMakeAssignment> *assignments, + QList<QMakeAssignment> *afterAssignments, + QString *additionalArguments); static QtVersion::QmakeBuildConfigs qmakeBuildConfigFromCmdArgs(QList<QMakeAssignment> *assignments, QtVersion::QmakeBuildConfigs defaultBuildConfig); // Used by QtOptionsPage diff --git a/src/plugins/qt4projectmanager/wizards/targetsetuppage.cpp b/src/plugins/qt4projectmanager/wizards/targetsetuppage.cpp index 227b0b5946fcda1f698c506df85220d502b58ea9..601472054e588d552f471581541fe824b0aec063 100644 --- a/src/plugins/qt4projectmanager/wizards/targetsetuppage.cpp +++ b/src/plugins/qt4projectmanager/wizards/targetsetuppage.cpp @@ -40,6 +40,7 @@ #include <projectexplorer/task.h> #include <projectexplorer/taskhub.h> #include <utils/qtcassert.h> +#include <utils/qtcprocess.h> #include <QtGui/QAction> #include <QtGui/QFileDialog> @@ -415,21 +416,20 @@ TargetSetupPage::recursivelyCheckDirectoryForBuild(const QString &directory, con info.isTemporary = true; } - QPair<QtVersion::QmakeBuildConfigs, QStringList> result = + QPair<QtVersion::QmakeBuildConfigs, QString> result = QtVersionManager::scanMakeFile(directory + "/Makefile", info.version->defaultBuildConfig()); info.buildConfig = result.first; - info.additionalArguments = Qt4BuildConfiguration::removeSpecFromArgumentList(result.second); - - QString parsedSpec = Qt4BuildConfiguration::extractSpecFromArgumentList(result.second, directory, info.version); + QString aa = result.second; + QString parsedSpec = Qt4BuildConfiguration::extractSpecFromArguments(&aa, directory, info.version); QString versionSpec = info.version->mkspec(); // Compare mkspecs and add to additional arguments if (parsedSpec.isEmpty() || parsedSpec == versionSpec || parsedSpec == "default") { // using the default spec, don't modify additional arguments } else { - info.additionalArguments.prepend(parsedSpec); - info.additionalArguments.prepend("-spec"); + info.additionalArguments = "-spec " + Utils::QtcProcess::quoteArg(parsedSpec); } + Utils::QtcProcess::addArgs(&info.additionalArguments, aa); results.append(info); return results; diff --git a/src/plugins/qt4projectmanager/wizards/targetsetuppage.h b/src/plugins/qt4projectmanager/wizards/targetsetuppage.h index e29b9343b71eabcdd686332df1cf6dc9e1e78b69..e354e6a243cd4dabd3d7e28934d14b6cebfe3e98 100644 --- a/src/plugins/qt4projectmanager/wizards/targetsetuppage.h +++ b/src/plugins/qt4projectmanager/wizards/targetsetuppage.h @@ -87,7 +87,7 @@ public: QtVersion *version; bool isTemporary; QtVersion::QmakeBuildConfigs buildConfig; - QStringList additionalArguments; + QString additionalArguments; QString directory; bool isExistingBuild; bool isShadowBuild; diff --git a/src/shared/symbianutils/launcher.cpp b/src/shared/symbianutils/launcher.cpp index 92829f53f42d1b8607c633b3c87815837fcc221b..57b484a422df0235c78a5a3b624ff6488d26e267 100644 --- a/src/shared/symbianutils/launcher.cpp +++ b/src/shared/symbianutils/launcher.cpp @@ -106,7 +106,7 @@ struct LauncherPrivate { CopyState m_copyState; DownloadState m_downloadState; QString m_fileName; - QStringList m_commandLineArgs; + QString m_commandLineArgs; QStringList m_installFileNames; int m_currentInstallFileName; int m_verbose; @@ -218,7 +218,7 @@ void Launcher::setInstallFileNames(const QStringList &names) d->m_currentInstallFileName = 0; } -void Launcher::setCommandLineArgs(const QStringList &args) +void Launcher::setCommandLineArgs(const QString &args) { d->m_commandLineArgs = args; } @@ -267,7 +267,7 @@ bool Launcher::startServer(QString *errorMessage) if (!d->m_fileName.isEmpty()) str << " Executable=" << d->m_fileName; if (!d->m_commandLineArgs.isEmpty()) - str << " Arguments= " << d->m_commandLineArgs.join(QString(QLatin1Char(' '))); + str << " Arguments= " << d->m_commandLineArgs; for (int i = 0; i < d->m_copyState.sourceFileNames.size(); ++i) { str << " Package/Source=" << d->m_copyState.sourceFileNames.at(i); str << " Remote Package/Destination=" << d->m_copyState.destinationFileNames.at(i); @@ -955,7 +955,7 @@ void Launcher::handleInstallPackageFinished(const TrkResult &result) } QByteArray Launcher::startProcessMessage(const QString &executable, - const QStringList &arguments) + const QString &arguments) { // It's not started yet QByteArray ba; @@ -965,7 +965,7 @@ QByteArray Launcher::startProcessMessage(const QString &executable, QByteArray commandLineBa = executable.toLocal8Bit(); commandLineBa.append(char(0)); if (!arguments.isEmpty()) - commandLineBa.append(arguments.join(QString(QLatin1Char(' '))).toLocal8Bit()); + commandLineBa.append(arguments.toLocal8Bit()); appendString(&ba, commandLineBa, TargetByteOrder, true); return ba; } diff --git a/src/shared/symbianutils/launcher.h b/src/shared/symbianutils/launcher.h index cfdb994f135ef740b0fde40f29e7299d5e1079d4..928e08c60421090415b0fcbb4ee9c77952db7a34 100644 --- a/src/shared/symbianutils/launcher.h +++ b/src/shared/symbianutils/launcher.h @@ -92,7 +92,7 @@ public: void setCopyFileNames(const QStringList &srcName, const QStringList &dstName); void setDownloadFileName(const QString &srcName, const QString &dstName); void setInstallFileNames(const QStringList &names); - void setCommandLineArgs(const QStringList &args); + void setCommandLineArgs(const QString &args); bool startServer(QString *errorMessage); void setInstallationMode(InstallationMode installation); void setInstallationDrive(char drive); @@ -122,7 +122,7 @@ public: // Create Trk message to start a process. static QByteArray startProcessMessage(const QString &executable, - const QStringList &arguments); + const QString &arguments); // Create Trk message to read memory static QByteArray readMemoryMessage(uint pid, uint tid, uint from, uint len); static QByteArray readRegistersMessage(uint pid, uint tid);