Commit e07c6383 authored by Tobias Hunger's avatar Tobias Hunger
Browse files

ProjectExplorer: Unify RunControl setup/teardown



Provide protected methods in RunControl to handle the notification
of when the RunControl starts and stops. Use these helpers to
move the isRunning() method into the RunConfiguration itself instead
of reimplementing it everywhere.

Change-Id: Ia8de42f7a6a14a049870d4e7fcb9af6756c2caa4
Reviewed-by: Maurice Kalinowski's avatarMaurice Kalinowski <maurice.kalinowski@qt.io>
Reviewed-by: default avatarhjk <hjk@qt.io>
Reviewed-by: Ulf Hermann's avatarUlf Hermann <ulf.hermann@qt.io>
Reviewed-by: Christian Kandeler's avatarChristian Kandeler <christian.kandeler@qt.io>
Reviewed-by: Tim Jenssen's avatarTim Jenssen <tim.jenssen@qt.io>
parent 329db5f4
......@@ -41,7 +41,6 @@ namespace Internal {
AndroidRunControl::AndroidRunControl(AndroidRunConfiguration *rc)
: RunControl(rc, ProjectExplorer::Constants::NORMAL_RUN_MODE)
, m_runner(new AndroidRunner(this, rc, ProjectExplorer::Constants::NORMAL_RUN_MODE))
, m_running(false)
{
setRunnable(m_runner->runnable());
setIcon(Utils::Icons::RUN_SMALL_TOOLBAR);
......@@ -54,8 +53,7 @@ AndroidRunControl::~AndroidRunControl()
void AndroidRunControl::start()
{
m_running = true;
emit started();
reportApplicationStart();
disconnect(m_runner, 0, this, 0);
connect(m_runner, &AndroidRunner::remoteErrorOutput,
......@@ -79,8 +77,7 @@ void AndroidRunControl::handleRemoteProcessFinished(const QString &error)
{
appendMessage(error, Utils::ErrorMessageFormat);
disconnect(m_runner, 0, this, 0);
m_running = false;
emit finished();
reportApplicationStop();
}
void AndroidRunControl::handleRemoteOutput(const QString &output)
......@@ -93,11 +90,6 @@ void AndroidRunControl::handleRemoteErrorOutput(const QString &output)
appendMessage(output, Utils::StdErrFormatSameLine);
}
bool AndroidRunControl::isRunning() const
{
return m_running;
}
QString AndroidRunControl::displayName() const
{
return m_runner->displayName();
......
......@@ -43,7 +43,6 @@ public:
void start() override;
StopResult stop() override;
bool isRunning() const override;
QString displayName() const override;
private:
......@@ -52,7 +51,6 @@ private:
void handleRemoteErrorOutput(const QString &output);
AndroidRunner *const m_runner;
bool m_running;
};
} // namespace Internal
......
......@@ -469,7 +469,7 @@ void ClangStaticAnalyzerRunControl::start()
m_success = false;
emit starting();
QTC_ASSERT(m_projectInfo.isValid(), emit finished(); return);
QTC_ASSERT(m_projectInfo.isValid(), reportApplicationStop(); return);
const Utils::FileName projectFile = m_projectInfo.project()->projectFilePath();
appendMessage(tr("Running Clang Static Analyzer on %1").arg(projectFile.toUserOutput())
+ QLatin1Char('\n'), Utils::NormalMessageFormat);
......@@ -485,7 +485,7 @@ void ClangStaticAnalyzerRunControl::start()
appendMessage(errorMessage + QLatin1Char('\n'), Utils::ErrorMessageFormat);
TaskHub::addTask(Task::Error, errorMessage, Debugger::Constants::ANALYZERTASK_ID);
TaskHub::requestPopup();
emit finished();
reportApplicationStop();
return;
}
......@@ -522,7 +522,7 @@ void ClangStaticAnalyzerRunControl::start()
appendMessage(errorMessage + QLatin1Char('\n'), Utils::ErrorMessageFormat);
TaskHub::addTask(Task::Error, errorMessage, Debugger::Constants::ANALYZERTASK_ID);
TaskHub::requestPopup();
emit finished();
reportApplicationStop();
return;
}
m_clangLogFileDir = temporaryDir.path();
......@@ -550,16 +550,15 @@ void ClangStaticAnalyzerRunControl::start()
qCDebug(LOG) << "Environment:" << m_environment;
m_runners.clear();
const int parallelRuns = ClangStaticAnalyzerSettings::instance()->simultaneousProcesses();
QTC_ASSERT(parallelRuns >= 1, emit finished(); return);
QTC_ASSERT(parallelRuns >= 1, reportApplicationStop(); return);
m_success = true;
m_running = true;
if (m_unitsToProcess.isEmpty()) {
finalize();
return;
}
emit started();
reportApplicationStart();
while (m_runners.size() < parallelRuns && !m_unitsToProcess.isEmpty())
analyzeNextFile();
......@@ -578,16 +577,10 @@ RunControl::StopResult ClangStaticAnalyzerRunControl::stop()
appendMessage(tr("Clang Static Analyzer stopped by user.") + QLatin1Char('\n'),
Utils::NormalMessageFormat);
m_progress.reportFinished();
m_running = false;
emit finished();
reportApplicationStop();
return RunControl::StoppedSynchronously;
}
bool ClangStaticAnalyzerRunControl::isRunning() const
{
return m_running;
}
void ClangStaticAnalyzerRunControl::analyzeNextFile()
{
if (m_progress.isFinished())
......@@ -701,8 +694,7 @@ void ClangStaticAnalyzerRunControl::finalize()
}
m_progress.reportFinished();
m_running = false;
emit finished();
reportApplicationStop();
}
} // namespace Internal
......
......@@ -58,7 +58,6 @@ public:
void start() override;
StopResult stop() override;
bool isRunning() const override;
bool success() const { return m_success; } // For testing.
bool supportsReRunning() const override { return false; }
......@@ -95,7 +94,6 @@ private:
int m_filesAnalyzed;
int m_filesNotAnalyzed;
bool m_success;
bool m_running = false;
};
} // namespace Internal
......
......@@ -112,8 +112,7 @@ DebuggerRunControl *createHelper(RunConfiguration *runConfig, Internal::Debugger
DebuggerRunControl::DebuggerRunControl(RunConfiguration *runConfig, DebuggerEngine *engine)
: RunControl(runConfig, DebugRunMode),
m_engine(engine),
m_running(false)
m_engine(engine)
{
setIcon(ProjectExplorer::Icons::DEBUG_START_SMALL_TOOLBAR);
connect(this, &RunControl::finished, this, &DebuggerRunControl::handleFinished);
......@@ -192,8 +191,8 @@ void DebuggerRunControl::start()
&& m_engine->runParameters().inferior.executable.isEmpty()
&& m_engine->runParameters().interpreter.isEmpty()) {
appendMessage(tr("No executable specified.") + QLatin1Char('\n'), ErrorMessageFormat);
emit started();
emit finished();
reportApplicationStart();
reportApplicationStop();
return;
}
......@@ -226,20 +225,18 @@ void DebuggerRunControl::start()
// We might get a synchronous startFailed() notification on Windows,
// when launching the process fails. Emit a proper finished() sequence.
emit started();
m_running = true;
reportApplicationStart();
m_engine->startDebugger(this);
if (m_running)
if (isRunning())
appendMessage(tr("Debugging starts") + QLatin1Char('\n'), NormalMessageFormat);
}
void DebuggerRunControl::startFailed()
{
appendMessage(tr("Debugging has failed") + QLatin1Char('\n'), NormalMessageFormat);
m_running = false;
emit finished();
reportApplicationStop();
m_engine->handleStartFailed();
}
......@@ -288,8 +285,7 @@ RunControl::StopResult DebuggerRunControl::stop()
void DebuggerRunControl::debuggingFinished()
{
m_running = false;
emit finished();
reportApplicationStop();
}
void DebuggerRunControl::showMessage(const QString &msg, int channel)
......@@ -297,11 +293,6 @@ void DebuggerRunControl::showMessage(const QString &msg, int channel)
m_engine->showMessage(msg, channel);
}
bool DebuggerRunControl::isRunning() const
{
return m_running;
}
DebuggerStartParameters &DebuggerRunControl::startParameters()
{
return m_engine->runParameters();
......
......@@ -69,7 +69,6 @@ public:
void start() override;
bool promptToStop(bool *prompt = 0) const override;
StopResult stop() override; // Called from SnapshotWindow.
bool isRunning() const override;
QString displayName() const override;
bool supportsReRunning() const override;
void handleApplicationOutput(const QString &msg, int channel);
......@@ -104,7 +103,6 @@ private:
Internal::DebuggerEngine *engine);
Internal::DebuggerEngine *m_engine;
bool m_running;
OutputProcessor *m_outputProcessor = 0;
};
......
......@@ -40,7 +40,6 @@ namespace Internal {
IosRunControl::IosRunControl(IosRunConfiguration *rc)
: RunControl(rc, ProjectExplorer::Constants::NORMAL_RUN_MODE)
, m_runner(new IosRunner(this, rc, false, QmlDebug::NoQmlDebugServices))
, m_running(false)
{
setIcon(Utils::Icons::RUN_SMALL_TOOLBAR);
}
......@@ -52,8 +51,7 @@ IosRunControl::~IosRunControl()
void IosRunControl::start()
{
m_running = true;
emit started();
reportApplicationStart();
disconnect(m_runner, 0, this, 0);
connect(m_runner, &IosRunner::errorMsg,
......@@ -79,8 +77,7 @@ void IosRunControl::handleRemoteProcessFinished(bool cleanEnd)
else
appendMessage(tr("Run ended."), Utils::NormalMessageFormat);
disconnect(m_runner, 0, this, 0);
m_running = false;
emit finished();
reportApplicationStop();
}
void IosRunControl::handleRemoteOutput(const QString &output)
......@@ -93,11 +90,6 @@ void IosRunControl::handleRemoteErrorOutput(const QString &output)
appendMessage(output, Utils::StdErrFormat);
}
bool IosRunControl::isRunning() const
{
return m_running;
}
QString IosRunControl::displayName() const
{
return m_runner->displayName();
......
......@@ -44,7 +44,6 @@ public:
void start() override;
StopResult stop() override;
bool isRunning() const override;
QString displayName() const override;
private:
......@@ -53,7 +52,6 @@ private:
void handleRemoteErrorOutput(const QString &output);
IosRunner *const m_runner;
bool m_running;
};
} // namespace Internal
......
......@@ -39,7 +39,6 @@ namespace Nim {
NimRunControl::NimRunControl(NimRunConfiguration *rc, Core::Id mode)
: RunControl(rc, mode)
, m_running(false)
, m_runnable(rc->runnable().as<StandardRunnable>())
{
connect(&m_applicationLauncher, &ApplicationLauncher::appendMessage,
......@@ -54,8 +53,7 @@ NimRunControl::NimRunControl(NimRunConfiguration *rc, Core::Id mode)
void NimRunControl::start()
{
emit started();
m_running = true;
reportApplicationStart();
m_applicationLauncher.start(m_runnable);
setApplicationProcessHandle(ProcessHandle(m_applicationLauncher.applicationPID()));
}
......@@ -66,11 +64,6 @@ ProjectExplorer::RunControl::StopResult NimRunControl::stop()
return StoppedSynchronously;
}
bool NimRunControl::isRunning() const
{
return m_running;
}
void NimRunControl::processStarted()
{
// Console processes only know their pid after being started
......@@ -79,7 +72,6 @@ void NimRunControl::processStarted()
void NimRunControl::processExited(int exitCode, QProcess::ExitStatus status)
{
m_running = false;
setApplicationProcessHandle(ProcessHandle());
QString msg;
if (status == QProcess::CrashExit) {
......@@ -90,7 +82,7 @@ void NimRunControl::processExited(int exitCode, QProcess::ExitStatus status)
.arg(QDir::toNativeSeparators(m_runnable.executable)).arg(exitCode);
}
appendMessage(msg + QLatin1Char('\n'), NormalMessageFormat);
emit finished();
reportApplicationStop();
}
void NimRunControl::slotAppendMessage(const QString &err, OutputFormat format)
......
......@@ -43,7 +43,6 @@ public:
void start() override;
StopResult stop() override;
bool isRunning() const override;
private:
void processStarted();
......@@ -51,7 +50,6 @@ private:
void slotAppendMessage(const QString &err, Utils::OutputFormat isError);
ProjectExplorer::ApplicationLauncher m_applicationLauncher;
bool m_running;
ProjectExplorer::StandardRunnable m_runnable;
};
......
......@@ -50,14 +50,12 @@ public:
void start() override;
StopResult stop() override;
bool isRunning() const override;
private:
void processStarted();
void processExited(int exitCode, QProcess::ExitStatus status);
ApplicationLauncher m_applicationLauncher;
bool m_running = false;
};
LocalApplicationRunControl::LocalApplicationRunControl(RunConfiguration *rc, Core::Id mode)
......@@ -79,17 +77,16 @@ void LocalApplicationRunControl::start()
{
QTC_ASSERT(runnable().is<StandardRunnable>(), return);
auto r = runnable().as<StandardRunnable>();
emit started();
reportApplicationStart();
if (r.executable.isEmpty()) {
appendMessage(tr("No executable specified.") + QLatin1Char('\n'), Utils::ErrorMessageFormat);
emit finished();
reportApplicationStop();
} else if (!QFileInfo::exists(r.executable)) {
appendMessage(tr("Executable %1 does not exist.")
.arg(QDir::toNativeSeparators(r.executable)) + QLatin1Char('\n'),
Utils::ErrorMessageFormat);
emit finished();
reportApplicationStop();
} else {
m_running = true;
QString msg = tr("Starting %1...").arg(QDir::toNativeSeparators(r.executable)) + QLatin1Char('\n');
appendMessage(msg, Utils::NormalMessageFormat);
m_applicationLauncher.start(r);
......@@ -103,11 +100,6 @@ LocalApplicationRunControl::StopResult LocalApplicationRunControl::stop()
return StoppedSynchronously;
}
bool LocalApplicationRunControl::isRunning() const
{
return m_running;
}
void LocalApplicationRunControl::processStarted()
{
// Console processes only know their pid after being started
......@@ -116,8 +108,6 @@ void LocalApplicationRunControl::processStarted()
void LocalApplicationRunControl::processExited(int exitCode, QProcess::ExitStatus status)
{
m_running = false;
setApplicationProcessHandle(ProcessHandle());
QString msg;
QString exe = runnable().as<StandardRunnable>().executable;
if (status == QProcess::CrashExit)
......@@ -125,7 +115,7 @@ void LocalApplicationRunControl::processExited(int exitCode, QProcess::ExitStatu
else
msg = tr("%1 exited with code %2").arg(QDir::toNativeSeparators(exe)).arg(exitCode);
appendMessage(msg + QLatin1Char('\n'), Utils::NormalMessageFormat);
emit finished();
reportApplicationStop();
}
// LocalApplicationRunControlFactory
......
......@@ -37,6 +37,7 @@
#include <utils/algorithm.h>
#include <utils/outputformatter.h>
#include <utils/checkablemessagebox.h>
#include <utils/qtcassert.h>
#include <coreplugin/icore.h>
#include <coreplugin/icontext.h>
......@@ -534,10 +535,12 @@ public:
// A handle to the actual application process.
Utils::ProcessHandle applicationProcessHandle;
bool isRunning = false;
#ifdef Q_OS_OSX
//these two are used to bring apps in the foreground on Mac
qint64 internalPid;
int foregroundCount;
qint64 internalPid;
#endif
};
......@@ -662,7 +665,7 @@ void RunControl::setApplicationProcessHandle(const ProcessHandle &handle)
{
if (d->applicationProcessHandle != handle) {
d->applicationProcessHandle = handle;
emit applicationProcessHandleChanged();
emit applicationProcessHandleChanged(QPrivateSignal());
}
}
......@@ -685,6 +688,11 @@ bool RunControl::promptToStop(bool *optionalPrompt) const
optionalPrompt);
}
bool RunControl::isRunning() const
{
return d->isRunning;
}
/*!
Prompts to terminate the application with the \gui {Do not ask again}
checkbox.
......@@ -732,6 +740,20 @@ void RunControl::bringApplicationToForeground(qint64 pid)
#endif
}
void RunControl::reportApplicationStart()
{
d->isRunning = true;
emit started(QPrivateSignal());
}
void RunControl::reportApplicationStop()
{
d->isRunning = false;
QTC_CHECK(d->applicationProcessHandle.isValid());
setApplicationProcessHandle(Utils::ProcessHandle());
emit finished(QPrivateSignal());
}
void RunControl::bringApplicationToForegroundInternal()
{
#ifdef Q_OS_OSX
......
......@@ -361,12 +361,14 @@ public:
virtual bool promptToStop(bool *optionalPrompt = nullptr) const;
virtual StopResult stop() = 0;
virtual bool isRunning() const = 0;
virtual bool supportsReRunning() const { return true; }
virtual QString displayName() const;
void setDisplayName(const QString &displayName);
bool isRunning() const;
void setIcon(const Utils::Icon &icon);
Utils::Icon icon() const;
......@@ -396,11 +398,14 @@ public slots:
signals:
void appendMessageRequested(ProjectExplorer::RunControl *runControl,
const QString &msg, Utils::OutputFormat format);
void started();
void finished();
void applicationProcessHandleChanged();
void started(QPrivateSignal); // Use reportApplicationStart!
void finished(QPrivateSignal); // Use reportApplicationStop!
void applicationProcessHandleChanged(QPrivateSignal); // Use setApplicationProcessHandle
protected:
void reportApplicationStart(); // Call this when the application starts to run
void reportApplicationStop(); // Call this when the application has stopped for any reason
bool showPromptToStopDialog(const QString &title, const QString &text,
const QString &stopButtonText = QString(),
const QString &cancelButtonText = QString(),
......
......@@ -225,7 +225,6 @@ public:
void start() override;
StopResult stop() override;
bool isRunning() const override { return m_running; }
private:
void processStarted();
......@@ -238,7 +237,6 @@ private:
QString m_commandLineArguments;
Utils::Environment m_environment;
ApplicationLauncher::Mode m_runMode;
bool m_running;
};
////////////////////////////////////////////////////////////////
......@@ -756,7 +754,7 @@ RunControl *PythonRunControlFactory::create(RunConfiguration *runConfiguration,
// PythonRunControl
PythonRunControl::PythonRunControl(PythonRunConfiguration *rc, Core::Id mode)
: RunControl(rc, mode), m_running(false)
: RunControl(rc, mode)
{
setIcon(Utils::Icons::RUN_SMALL_TOOLBAR);
......@@ -778,16 +776,15 @@ PythonRunControl::PythonRunControl(PythonRunConfiguration *rc, Core::Id mode)
void PythonRunControl::start()
{
emit started();
reportApplicationStart();
if (m_interpreter.isEmpty()) {
appendMessage(tr("No Python interpreter specified.") + '\n', Utils::ErrorMessageFormat);
emit finished();
reportApplicationStop();
} else if (!QFileInfo::exists(m_interpreter)) {
appendMessage(tr("Python interpreter %1 does not exist.").arg(QDir::toNativeSeparators(m_interpreter)) + '\n',
Utils::ErrorMessageFormat);
emit finished();
reportApplicationStop();
} else {
m_running = true;
QString msg = tr("Starting %1...").arg(QDir::toNativeSeparators(m_interpreter)) + '\n';
appendMessage(msg, Utils::NormalMessageFormat);
......@@ -822,8 +819,6 @@ void PythonRunControl::processStarted()
void PythonRunControl::processExited(int exitCode, QProcess::ExitStatus status)
{
m_running = false;
setApplicationProcessHandle(ProcessHandle());
QString msg;
if (status == QProcess::CrashExit) {
msg = tr("%1 crashed")
......@@ -833,7 +828,7 @@ void PythonRunControl::processExited(int exitCode, QProcess::ExitStatus status)
.arg(QDir::toNativeSeparators(m_interpreter)).arg(exitCode);
}
appendMessage(msg + '\n', Utils::NormalMessageFormat);
emit finished();
reportApplicationStop();
}
void PythonRunConfigurationWidget::setInterpreter(const QString &interpreter)
......
......@@ -70,7 +70,6 @@ public:
Internal::QmlProfilerTool *m_tool = 0;
QmlProfilerStateManager *m_profilerState = 0;
QTimer m_noDebugOutputTimer;
bool m_running = false;
};
//
......@@ -96,17 +95,18 @@ QmlProfilerRunControl::QmlProfilerRunControl(RunConfiguration *runConfiguration,
QmlProfilerRunControl::~QmlProfilerRunControl()
{
if (d->m_running && d->m_profilerState)
if (isRunning() && d->m_profilerState)
stop();
delete d;
}
void QmlProfilerRunControl::start()
{
reportApplicationStart();
d->m_tool->finalizeRunControl(this);
QTC_ASSERT(d->m_profilerState, finished(); return);
QTC_ASSERT(d->m_profilerState, reportApplicationStop(); return);
QTC_ASSERT(connection().is<AnalyzerConnection>(), finished(); return);
QTC_ASSERT(connection().is<AnalyzerConnection>(), reportApplicationStop(); return);
auto conn = connection().as<AnalyzerConnection>();
if (conn.analyzerPort.isValid())
......@@ -115,13 +115,11 @@ void QmlProfilerRunControl::start()
d->m_noDebugOutputTimer.start();
d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppRunning);
d->m_running = true;
emit starting();
}
RunControl