fix "Open Command Prompt Here" on windows with qt 5.8

qt 5.8 made QProcess::startDetached()'s behavior consistent with
start(), which means it won't open a console any more. however, qtc
relied on this (unspecified) behavior.

the correct solution is to add a static function startTerminalEmulator()
to ConsoleProcess, which already has most of the necessary code anyway.

Task-number: QTCREATORBUG-17439
Change-Id: Icf04666869ce6593555302a54c49331a29846a99
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
Reviewed-by: Robert Loehning <robert.loehning@qt.io>
This commit is contained in:
Oswald Buddenhagen
2017-01-11 13:55:31 +01:00
committed by Robert Loehning
parent 4b0016fb2a
commit ec50c146b3
4 changed files with 37 additions and 19 deletions

View File

@@ -91,6 +91,8 @@ public:
static QString terminalEmulator(const QSettings *settings, bool nonEmpty = true); static QString terminalEmulator(const QSettings *settings, bool nonEmpty = true);
static void setTerminalEmulator(QSettings *settings, const QString &term); static void setTerminalEmulator(QSettings *settings, const QString &term);
static bool startTerminalEmulator(QSettings *settings, const QString &workingDir);
signals: signals:
void error(QProcess::ProcessError error); void error(QProcess::ProcessError error);
void processError(const QString &errorString); void processError(const QString &errorString);

View File

@@ -395,4 +395,10 @@ QStringList ConsoleProcess::availableTerminalEmulators()
return result; return result;
} }
bool ConsoleProcess::startTerminalEmulator(QSettings *settings, const QString &workingDir)
{
const QString emu = QtcProcess::splitArgs(terminalEmulator(settings)).takeFirst();
return QProcess::startDetached(emu, QStringList(), workingDir);
}
} // namespace Utils } // namespace Utils

View File

@@ -389,4 +389,31 @@ void ConsoleProcess::setSettings(QSettings *settings)
// Not used on Windows // Not used on Windows
} }
bool ConsoleProcess::startTerminalEmulator(QSettings *, const QString &workingDir)
{
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
PROCESS_INFORMATION pinfo;
ZeroMemory(&pinfo, sizeof(pinfo));
QString cmdLine = createWinCommandline(
QString::fromLocal8Bit(qgetenv("COMSPEC")), QString());
// cmdLine is assumed to be detached -
// https://blogs.msdn.microsoft.com/oldnewthing/20090601-00/?p=18083
bool success = CreateProcessW(0, (WCHAR *)cmdLine.utf16(),
0, 0, FALSE, CREATE_NEW_CONSOLE,
0, workingDir.isEmpty() ? 0 : (WCHAR *)workingDir.utf16(),
&si, &pinfo);
if (success) {
CloseHandle(pinfo.hThread);
CloseHandle(pinfo.hProcess);
}
return success;
}
} // namespace Utils } // namespace Utils

View File

@@ -31,15 +31,14 @@
#include <coreplugin/iversioncontrol.h> #include <coreplugin/iversioncontrol.h>
#include <coreplugin/vcsmanager.h> #include <coreplugin/vcsmanager.h>
#include <utils/consoleprocess.h> #include <utils/consoleprocess.h>
#include <utils/environment.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <utils/qtcprocess.h>
#include <utils/unixutils.h> #include <utils/unixutils.h>
#include <QApplication> #include <QApplication>
#include <QDir> #include <QDir>
#include <QFileInfo> #include <QFileInfo>
#include <QMessageBox> #include <QMessageBox>
#include <QProcess>
#include <QPushButton> #include <QPushButton>
#include <QWidget> #include <QWidget>
@@ -110,27 +109,11 @@ void FileUtils::showInGraphicalShell(QWidget *parent, const QString &pathIn)
void FileUtils::openTerminal(const QString &path) void FileUtils::openTerminal(const QString &path)
{ {
// Get terminal application
QString terminalEmulator;
QStringList args;
const OsType hostOs = HostOsInfo::hostOs();
if (hostOs == OsTypeWindows) {
terminalEmulator = ConsoleProcess::defaultTerminalEmulator();
} else if (hostOs == OsTypeMac) {
terminalEmulator = ICore::resourcePath()
+ QLatin1String("/scripts/openTerminal.command");
} else {
args = QtcProcess::splitArgs(ConsoleProcess::terminalEmulator(ICore::settings()), hostOs);
terminalEmulator = args.takeFirst();
args.append(QString::fromLocal8Bit(qgetenv("SHELL")));
}
// Launch terminal with working directory set.
const QFileInfo fileInfo(path); const QFileInfo fileInfo(path);
const QString pwd = QDir::toNativeSeparators(fileInfo.isDir() ? const QString pwd = QDir::toNativeSeparators(fileInfo.isDir() ?
fileInfo.absoluteFilePath() : fileInfo.absoluteFilePath() :
fileInfo.absolutePath()); fileInfo.absolutePath());
QProcess::startDetached(terminalEmulator, args, pwd); ConsoleProcess::startTerminalEmulator(ICore::settings(), pwd);
} }
QString FileUtils::msgFindInDirectory() QString FileUtils::msgFindInDirectory()