forked from qt-creator/qt-creator
ProjectExplorer: Split RunControl states further
This adds enough hooks to enable the base RunControl to take over the task of most of the current ad-hoc "state machine" implementations in derived RunControls (only exception is "intra-debugger" Start/Stop handling), including error reporting. The idea is to migrate "downstream" uses and finally remove the custom state handling everywhere. With this setup here, both varieties of RunControls can co-exist for a while: New-style uses the Tool/Target state handling triggered by the base RunControl::start implementation, old-style had this function = 0, so all have their custom start() implementation. 'SimpleRunControl' derived cases (Local/RemoteLinux/Python run) already use new-style with this patch SimpleRunControl doesn't re-implement start(). Change-Id: I508f5ed05c557ca7188af92f9d9c8d00e2a4acfe Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
@@ -399,7 +399,7 @@ void AppOutputPane::updateBehaviorSettings()
|
|||||||
|
|
||||||
void AppOutputPane::createNewOutputWindow(RunControl *rc)
|
void AppOutputPane::createNewOutputWindow(RunControl *rc)
|
||||||
{
|
{
|
||||||
connect(rc, &RunControl::started,
|
connect(rc, &RunControl::aboutToStart,
|
||||||
this, &AppOutputPane::slotRunControlStarted);
|
this, &AppOutputPane::slotRunControlStarted);
|
||||||
connect(rc, &RunControl::finished,
|
connect(rc, &RunControl::finished,
|
||||||
this, &AppOutputPane::slotRunControlFinished);
|
this, &AppOutputPane::slotRunControlFinished);
|
||||||
@@ -703,7 +703,6 @@ void AppOutputPane::slotRunControlStarted()
|
|||||||
|
|
||||||
if (current && current == sender())
|
if (current && current == sender())
|
||||||
enableButtons(current, true); // RunControl::isRunning() cannot be trusted in signal handler.
|
enableButtons(current, true); // RunControl::isRunning() cannot be trusted in signal handler.
|
||||||
emit runControlStarted(current);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppOutputPane::slotRunControlFinished()
|
void AppOutputPane::slotRunControlFinished()
|
||||||
@@ -734,7 +733,7 @@ void AppOutputPane::slotRunControlFinished2(RunControl *sender)
|
|||||||
|
|
||||||
m_runControlTabs.at(senderIndex).window->setFormatter(nullptr); // Reset formater for this RC
|
m_runControlTabs.at(senderIndex).window->setFormatter(nullptr); // Reset formater for this RC
|
||||||
|
|
||||||
emit runControlFinished(sender);
|
ProjectExplorerPlugin::instance()->updateRunActions();
|
||||||
|
|
||||||
if (!isRunning())
|
if (!isRunning())
|
||||||
emit allRunControlsFinished();
|
emit allRunControlsFinished();
|
||||||
|
|||||||
@@ -93,8 +93,6 @@ public:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void allRunControlsFinished();
|
void allRunControlsFinished();
|
||||||
void runControlStarted(ProjectExplorer::RunControl *rc);
|
|
||||||
void runControlFinished(ProjectExplorer::RunControl *rc);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// ApplicationOutput specifics
|
// ApplicationOutput specifics
|
||||||
|
|||||||
@@ -613,13 +613,6 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
|
|||||||
connect(SessionManager::instance(), &SessionManager::projectRemoved,
|
connect(SessionManager::instance(), &SessionManager::projectRemoved,
|
||||||
dd->m_outputPane, &AppOutputPane::projectRemoved);
|
dd->m_outputPane, &AppOutputPane::projectRemoved);
|
||||||
|
|
||||||
connect(dd->m_outputPane, &AppOutputPane::runControlStarted,
|
|
||||||
this, &ProjectExplorerPlugin::runControlStarted);
|
|
||||||
connect(dd->m_outputPane, &AppOutputPane::runControlFinished,
|
|
||||||
this, &ProjectExplorerPlugin::runControlFinished);
|
|
||||||
connect(dd->m_outputPane, &AppOutputPane::runControlFinished,
|
|
||||||
this, &ProjectExplorerPlugin::updateRunActions);
|
|
||||||
|
|
||||||
addAutoReleasedObject(new AllProjectsFilter);
|
addAutoReleasedObject(new AllProjectsFilter);
|
||||||
addAutoReleasedObject(new CurrentProjectFilter);
|
addAutoReleasedObject(new CurrentProjectFilter);
|
||||||
|
|
||||||
|
|||||||
@@ -162,8 +162,6 @@ public:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void finishedInitialization();
|
void finishedInitialization();
|
||||||
void runControlStarted(ProjectExplorer::RunControl *rc);
|
|
||||||
void runControlFinished(ProjectExplorer::RunControl *rc);
|
|
||||||
|
|
||||||
// Is emitted when a project has been added/removed,
|
// Is emitted when a project has been added/removed,
|
||||||
// or the file list of a specific project has changed.
|
// or the file list of a specific project has changed.
|
||||||
|
|||||||
@@ -58,6 +58,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
using namespace ProjectExplorer::Internal;
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
|
|
||||||
@@ -503,11 +504,23 @@ IRunConfigurationAspect *IRunControlFactory::createRunConfigurationAspect(RunCon
|
|||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class RunControlPrivate
|
ToolRunner *trivialToolRunner()
|
||||||
|
{
|
||||||
|
static ToolRunner runner(nullptr);
|
||||||
|
return &runner;
|
||||||
|
}
|
||||||
|
|
||||||
|
TargetRunner *trivialTargetRunner()
|
||||||
|
{
|
||||||
|
static TargetRunner runner(nullptr);
|
||||||
|
return &runner;
|
||||||
|
}
|
||||||
|
|
||||||
|
class RunControlPrivate : public QObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RunControlPrivate(RunConfiguration *runConfiguration, Core::Id mode)
|
RunControlPrivate(RunControl *parent, RunConfiguration *runConfiguration, Core::Id mode)
|
||||||
: runMode(mode), runConfiguration(runConfiguration)
|
: q(parent), runMode(mode), runConfiguration(runConfiguration)
|
||||||
{
|
{
|
||||||
if (runConfiguration) {
|
if (runConfiguration) {
|
||||||
displayName = runConfiguration->displayName();
|
displayName = runConfiguration->displayName();
|
||||||
@@ -519,11 +532,47 @@ public:
|
|||||||
|
|
||||||
~RunControlPrivate()
|
~RunControlPrivate()
|
||||||
{
|
{
|
||||||
delete targetRunner;
|
QTC_CHECK(state == State::Stopped);
|
||||||
delete toolRunner;
|
if (targetRunner != trivialTargetRunner())
|
||||||
|
delete targetRunner;
|
||||||
|
if (toolRunner != trivialToolRunner())
|
||||||
|
delete toolRunner;
|
||||||
delete outputFormatter;
|
delete outputFormatter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class State {
|
||||||
|
Initialized, // Default value after creation.
|
||||||
|
TargetPreparing, // initiateStart() was called, target boots up, connects, etc
|
||||||
|
ToolPreparing, // Target is acessible, tool boots
|
||||||
|
TargetStarting, // Late corrections on the target side after tool is available.
|
||||||
|
ToolStarting, // Actual process/tool starts.
|
||||||
|
Running, // All good and running.
|
||||||
|
ToolStopping, // initiateStop() was called, stop application/tool
|
||||||
|
TargetStopping, // Potential clean up on target, set idle state, etc.
|
||||||
|
Stopped, // all good, but stopped. Can possibly be re-started
|
||||||
|
};
|
||||||
|
Q_ENUM(State)
|
||||||
|
|
||||||
|
void checkState(State expectedState);
|
||||||
|
void setState(State state);
|
||||||
|
|
||||||
|
void initiateStart();
|
||||||
|
void onTargetPrepared();
|
||||||
|
void onToolPrepared();
|
||||||
|
void onTargetStarted();
|
||||||
|
void onToolStarted();
|
||||||
|
|
||||||
|
void initiateStop();
|
||||||
|
void onToolStopped();
|
||||||
|
void onTargetStopped();
|
||||||
|
|
||||||
|
void onToolFailed(const QString &msg);
|
||||||
|
void onTargetFailed(const QString &msg);
|
||||||
|
void handleFailure();
|
||||||
|
|
||||||
|
static bool isAllowedTransition(State from, State to);
|
||||||
|
|
||||||
|
RunControl *q;
|
||||||
QString displayName;
|
QString displayName;
|
||||||
Runnable runnable;
|
Runnable runnable;
|
||||||
IDevice::ConstPtr device;
|
IDevice::ConstPtr device;
|
||||||
@@ -539,7 +588,7 @@ public:
|
|||||||
// A handle to the actual application process.
|
// A handle to the actual application process.
|
||||||
Utils::ProcessHandle applicationProcessHandle;
|
Utils::ProcessHandle applicationProcessHandle;
|
||||||
|
|
||||||
RunControl::State state = RunControl::State::Initialized;
|
State state = State::Initialized;
|
||||||
|
|
||||||
#ifdef Q_OS_OSX
|
#ifdef Q_OS_OSX
|
||||||
// This is used to bring apps in the foreground on Mac
|
// This is used to bring apps in the foreground on Mac
|
||||||
@@ -549,8 +598,10 @@ public:
|
|||||||
|
|
||||||
} // Internal
|
} // Internal
|
||||||
|
|
||||||
|
using namespace Internal;
|
||||||
|
|
||||||
RunControl::RunControl(RunConfiguration *runConfiguration, Core::Id mode) :
|
RunControl::RunControl(RunConfiguration *runConfiguration, Core::Id mode) :
|
||||||
d(new Internal::RunControlPrivate(runConfiguration, mode))
|
d(new RunControlPrivate(this, runConfiguration, mode))
|
||||||
{
|
{
|
||||||
#ifdef WITH_JOURNALD
|
#ifdef WITH_JOURNALD
|
||||||
JournaldWatcher::instance()->subscribe(this, [this](const JournaldWatcher::LogEntry &entry) {
|
JournaldWatcher::instance()->subscribe(this, [this](const JournaldWatcher::LogEntry &entry) {
|
||||||
@@ -581,14 +632,116 @@ RunControl::~RunControl()
|
|||||||
|
|
||||||
void RunControl::initiateStart()
|
void RunControl::initiateStart()
|
||||||
{
|
{
|
||||||
setState(State::Starting);
|
if (!d->targetRunner)
|
||||||
QTimer::singleShot(0, this, &RunControl::start);
|
setTargetRunner(trivialTargetRunner());
|
||||||
|
if (!d->toolRunner)
|
||||||
|
setToolRunner(trivialToolRunner());
|
||||||
|
emit aboutToStart();
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunControl::start()
|
||||||
|
{
|
||||||
|
d->initiateStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunControl::initiateStop()
|
void RunControl::initiateStop()
|
||||||
{
|
{
|
||||||
setState(State::Stopping);
|
stop();
|
||||||
QTimer::singleShot(0, this, &RunControl::stop);
|
}
|
||||||
|
|
||||||
|
void RunControl::stop()
|
||||||
|
{
|
||||||
|
d->initiateStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunControlPrivate::initiateStart()
|
||||||
|
{
|
||||||
|
checkState(State::Initialized);
|
||||||
|
setState(State::TargetPreparing);
|
||||||
|
targetRunner->prepare();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunControlPrivate::onTargetPrepared()
|
||||||
|
{
|
||||||
|
checkState(State::TargetPreparing);
|
||||||
|
setState(State::ToolPreparing);
|
||||||
|
toolRunner->prepare();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunControlPrivate::onToolPrepared()
|
||||||
|
{
|
||||||
|
checkState(State::ToolPreparing);
|
||||||
|
setState(State::TargetStarting);
|
||||||
|
targetRunner->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunControlPrivate::onTargetStarted()
|
||||||
|
{
|
||||||
|
checkState(State::TargetStarting);
|
||||||
|
setState(State::ToolStarting);
|
||||||
|
toolRunner->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunControlPrivate::onToolStarted()
|
||||||
|
{
|
||||||
|
checkState(State::ToolStarting);
|
||||||
|
setState(State::Running);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunControlPrivate::initiateStop()
|
||||||
|
{
|
||||||
|
checkState(State::Running);
|
||||||
|
setState(State::ToolStopping);
|
||||||
|
toolRunner->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunControlPrivate::onToolStopped()
|
||||||
|
{
|
||||||
|
checkState(State::ToolStopping);
|
||||||
|
setState(State::TargetStopping);
|
||||||
|
targetRunner->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunControlPrivate::onTargetStopped()
|
||||||
|
{
|
||||||
|
checkState(State::TargetStopping);
|
||||||
|
setState(State::Stopped);
|
||||||
|
QTC_CHECK(applicationProcessHandle.isValid());
|
||||||
|
q->setApplicationProcessHandle(Utils::ProcessHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunControlPrivate::onTargetFailed(const QString &msg)
|
||||||
|
{
|
||||||
|
if (!msg.isEmpty())
|
||||||
|
q->appendMessage(msg, ErrorMessageFormat);
|
||||||
|
|
||||||
|
handleFailure();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunControlPrivate::onToolFailed(const QString &msg)
|
||||||
|
{
|
||||||
|
if (!msg.isEmpty())
|
||||||
|
q->appendMessage(msg, ErrorMessageFormat);
|
||||||
|
|
||||||
|
handleFailure();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunControlPrivate::handleFailure()
|
||||||
|
{
|
||||||
|
switch (state) {
|
||||||
|
case State::Initialized:
|
||||||
|
case State::TargetPreparing:
|
||||||
|
case State::ToolPreparing:
|
||||||
|
case State::TargetStarting:
|
||||||
|
case State::ToolStarting:
|
||||||
|
case State::Running:
|
||||||
|
case State::ToolStopping:
|
||||||
|
case State::TargetStopping:
|
||||||
|
case State::Stopped:
|
||||||
|
setState(State::Stopped);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::OutputFormatter *RunControl::outputFormatter() const
|
Utils::OutputFormatter *RunControl::outputFormatter() const
|
||||||
@@ -629,6 +782,10 @@ ToolRunner *RunControl::toolRunner() const
|
|||||||
void RunControl::setToolRunner(ToolRunner *tool)
|
void RunControl::setToolRunner(ToolRunner *tool)
|
||||||
{
|
{
|
||||||
d->toolRunner = tool;
|
d->toolRunner = tool;
|
||||||
|
connect(d->toolRunner, &ToolRunner::prepared, d, &RunControlPrivate::onToolPrepared);
|
||||||
|
connect(d->toolRunner, &ToolRunner::started, d, &RunControlPrivate::onToolStarted);
|
||||||
|
connect(d->toolRunner, &ToolRunner::stopped, d, &RunControlPrivate::onToolStopped);
|
||||||
|
connect(d->toolRunner, &ToolRunner::failed, d, &RunControlPrivate::onToolFailed);
|
||||||
}
|
}
|
||||||
|
|
||||||
TargetRunner *RunControl::targetRunner() const
|
TargetRunner *RunControl::targetRunner() const
|
||||||
@@ -639,6 +796,10 @@ TargetRunner *RunControl::targetRunner() const
|
|||||||
void RunControl::setTargetRunner(TargetRunner *runner)
|
void RunControl::setTargetRunner(TargetRunner *runner)
|
||||||
{
|
{
|
||||||
d->targetRunner = runner;
|
d->targetRunner = runner;
|
||||||
|
connect(d->targetRunner, &TargetRunner::prepared, d, &RunControlPrivate::onTargetPrepared);
|
||||||
|
connect(d->targetRunner, &TargetRunner::started, d, &RunControlPrivate::onTargetStarted);
|
||||||
|
connect(d->targetRunner, &TargetRunner::stopped, d, &RunControlPrivate::onTargetStopped);
|
||||||
|
connect(d->targetRunner, &TargetRunner::failed, d, &RunControlPrivate::onTargetFailed);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString RunControl::displayName() const
|
QString RunControl::displayName() const
|
||||||
@@ -732,7 +893,7 @@ bool RunControl::promptToStop(bool *optionalPrompt) const
|
|||||||
|
|
||||||
bool RunControl::isRunning() const
|
bool RunControl::isRunning() const
|
||||||
{
|
{
|
||||||
return d->state == State::Running;
|
return d->state == RunControlPrivate::State::Running;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -771,31 +932,58 @@ bool RunControl::showPromptToStopDialog(const QString &title,
|
|||||||
return close;
|
return close;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isAllowedTransition(RunControl::State from, RunControl::State to)
|
bool RunControlPrivate::isAllowedTransition(State from, State to)
|
||||||
{
|
{
|
||||||
switch (from) {
|
switch (from) {
|
||||||
case RunControl::State::Initialized:
|
case State::Initialized:
|
||||||
return to == RunControl::State::Starting;
|
return to == State::TargetPreparing;
|
||||||
case RunControl::State::Starting:
|
case State::TargetPreparing:
|
||||||
return to == RunControl::State::Running;
|
return to == State::ToolPreparing;
|
||||||
case RunControl::State::Running:
|
case State::ToolPreparing:
|
||||||
return to == RunControl::State::Stopping
|
return to == State::TargetStarting;
|
||||||
|| to == RunControl::State::Stopped;
|
case State::TargetStarting:
|
||||||
case RunControl::State::Stopping:
|
return to == State::ToolStarting;
|
||||||
return to == RunControl::State::Stopped;
|
case State::ToolStarting:
|
||||||
case RunControl::State::Stopped:
|
return to == State::Running;
|
||||||
|
case State::Running:
|
||||||
|
return to == State::ToolStopping
|
||||||
|
|| to == State::Stopped;
|
||||||
|
case State::ToolStopping:
|
||||||
|
return to == State::TargetStopping;
|
||||||
|
case State::TargetStopping:
|
||||||
|
return to == State::Stopped;
|
||||||
|
case State::Stopped:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
|
qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunControl::setState(RunControl::State state)
|
void RunControlPrivate::checkState(State expectedState)
|
||||||
{
|
{
|
||||||
if (!isAllowedTransition(d->state, state)) {
|
if (state != expectedState)
|
||||||
qDebug() << "Invalid run state transition from " << d->state << " to " << state;
|
qDebug() << "Unexpected state " << expectedState << " have: " << state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunControlPrivate::setState(State newState)
|
||||||
|
{
|
||||||
|
if (!isAllowedTransition(state, newState))
|
||||||
|
qDebug() << "Invalid run state transition from " << state << " to " << newState;
|
||||||
|
|
||||||
|
state = newState;
|
||||||
|
|
||||||
|
// Extra reporting.
|
||||||
|
switch (state) {
|
||||||
|
case State::Running:
|
||||||
|
emit q->started();
|
||||||
|
break;
|
||||||
|
case State::Stopped:
|
||||||
|
emit q->finished();
|
||||||
|
state = State::Initialized; // Reset for potential re-running.
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
d->state = state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -813,35 +1001,23 @@ void RunControl::bringApplicationToForeground()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunControl::start()
|
|
||||||
{
|
|
||||||
QTC_ASSERT(d->targetRunner, return);
|
|
||||||
d->targetRunner->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RunControl::stop()
|
|
||||||
{
|
|
||||||
QTC_ASSERT(d->targetRunner, return);
|
|
||||||
d->targetRunner->stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RunControl::reportApplicationStart()
|
void RunControl::reportApplicationStart()
|
||||||
{
|
{
|
||||||
setState(State::Running);
|
// QTC_CHECK(false); FIXME: Legacy, ToolRunner should emit started() instead.
|
||||||
emit started(QPrivateSignal());
|
d->onToolStarted();
|
||||||
|
emit started();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunControl::reportApplicationStop()
|
void RunControl::reportApplicationStop()
|
||||||
{
|
{
|
||||||
if (d->state == State::Stopped) {
|
// QTC_CHECK(false); FIXME: Legacy, ToolRunner should emit stopped() instead.
|
||||||
|
if (d->state == RunControlPrivate::State::Stopped) {
|
||||||
// FIXME: Currently various tool implementations call reportApplicationStop()
|
// FIXME: Currently various tool implementations call reportApplicationStop()
|
||||||
// multiple times. Fix it there and then add a soft assert here.
|
// multiple times. Fix it there and then add a soft assert here.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setState(State::Stopped);
|
d->onToolStopped();
|
||||||
QTC_CHECK(d->applicationProcessHandle.isValid());
|
emit finished();
|
||||||
setApplicationProcessHandle(Utils::ProcessHandle());
|
|
||||||
emit finished(QPrivateSignal());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunControl::bringApplicationToForegroundInternal()
|
void RunControl::bringApplicationToForegroundInternal()
|
||||||
@@ -880,6 +1056,9 @@ static bool isSynchronousLauncher(RunControl *runControl)
|
|||||||
return !deviceId.isValid() || deviceId == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
|
return !deviceId.isValid() || deviceId == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// SimpleTargetRunner
|
||||||
|
|
||||||
SimpleTargetRunner::SimpleTargetRunner(RunControl *runControl)
|
SimpleTargetRunner::SimpleTargetRunner(RunControl *runControl)
|
||||||
: TargetRunner(runControl)
|
: TargetRunner(runControl)
|
||||||
{
|
{
|
||||||
@@ -887,7 +1066,6 @@ SimpleTargetRunner::SimpleTargetRunner(RunControl *runControl)
|
|||||||
|
|
||||||
void SimpleTargetRunner::start()
|
void SimpleTargetRunner::start()
|
||||||
{
|
{
|
||||||
runControl()->reportApplicationStart();
|
|
||||||
m_launcher.disconnect(this);
|
m_launcher.disconnect(this);
|
||||||
|
|
||||||
Runnable r = runControl()->runnable();
|
Runnable r = runControl()->runnable();
|
||||||
@@ -904,27 +1082,20 @@ void SimpleTargetRunner::start()
|
|||||||
QTC_ASSERT(r.is<StandardRunnable>(), return);
|
QTC_ASSERT(r.is<StandardRunnable>(), return);
|
||||||
const QString executable = r.as<StandardRunnable>().executable;
|
const QString executable = r.as<StandardRunnable>().executable;
|
||||||
if (executable.isEmpty()) {
|
if (executable.isEmpty()) {
|
||||||
appendMessage(RunControl::tr("No executable specified.") + '\n',
|
emit failed(RunControl::tr("No executable specified.") + '\n');
|
||||||
Utils::ErrorMessageFormat);
|
|
||||||
runControl()->reportApplicationStop();
|
|
||||||
} else if (!QFileInfo::exists(executable)) {
|
} else if (!QFileInfo::exists(executable)) {
|
||||||
appendMessage(RunControl::tr("Executable %1 does not exist.")
|
emit failed(RunControl::tr("Executable %1 does not exist.")
|
||||||
.arg(QDir::toNativeSeparators(executable)) + '\n',
|
.arg(QDir::toNativeSeparators(executable)) + '\n');
|
||||||
Utils::ErrorMessageFormat);
|
|
||||||
runControl()->reportApplicationStop();
|
|
||||||
} else {
|
} else {
|
||||||
QString msg = RunControl::tr("Starting %1...").arg(QDir::toNativeSeparators(executable)) + '\n';
|
QString msg = RunControl::tr("Starting %1...").arg(QDir::toNativeSeparators(executable)) + '\n';
|
||||||
appendMessage(msg, Utils::NormalMessageFormat);
|
appendMessage(msg, Utils::NormalMessageFormat);
|
||||||
m_launcher.start(r);
|
m_launcher.start(r);
|
||||||
runControl()->setApplicationProcessHandle(m_launcher.applicationPID());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
connect(&m_launcher, &ApplicationLauncher::reportError,
|
connect(&m_launcher, &ApplicationLauncher::reportError,
|
||||||
this, [this](const QString &error) {
|
this, &TargetRunner::failed);
|
||||||
appendMessage(error, Utils::ErrorMessageFormat);
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(&m_launcher, &ApplicationLauncher::remoteStderr,
|
connect(&m_launcher, &ApplicationLauncher::remoteStderr,
|
||||||
this, [this](const QByteArray &output) {
|
this, [this](const QByteArray &output) {
|
||||||
@@ -939,7 +1110,7 @@ void SimpleTargetRunner::start()
|
|||||||
connect(&m_launcher, &ApplicationLauncher::finished,
|
connect(&m_launcher, &ApplicationLauncher::finished,
|
||||||
this, [this] {
|
this, [this] {
|
||||||
m_launcher.disconnect(this);
|
m_launcher.disconnect(this);
|
||||||
runControl()->reportApplicationStop();
|
emit stopped();
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(&m_launcher, &ApplicationLauncher::reportProgress,
|
connect(&m_launcher, &ApplicationLauncher::reportProgress,
|
||||||
@@ -959,6 +1130,7 @@ void SimpleTargetRunner::stop()
|
|||||||
void SimpleTargetRunner::onProcessStarted()
|
void SimpleTargetRunner::onProcessStarted()
|
||||||
{
|
{
|
||||||
// Console processes only know their pid after being started
|
// Console processes only know their pid after being started
|
||||||
|
emit started();
|
||||||
runControl()->setApplicationProcessHandle(m_launcher.applicationPID());
|
runControl()->setApplicationProcessHandle(m_launcher.applicationPID());
|
||||||
runControl()->bringApplicationToForeground();
|
runControl()->bringApplicationToForeground();
|
||||||
}
|
}
|
||||||
@@ -972,15 +1144,17 @@ void SimpleTargetRunner::onProcessFinished(int exitCode, QProcess::ExitStatus st
|
|||||||
else
|
else
|
||||||
msg = tr("%1 exited with code %2").arg(QDir::toNativeSeparators(exe)).arg(exitCode);
|
msg = tr("%1 exited with code %2").arg(QDir::toNativeSeparators(exe)).arg(exitCode);
|
||||||
appendMessage(msg + '\n', Utils::NormalMessageFormat);
|
appendMessage(msg + '\n', Utils::NormalMessageFormat);
|
||||||
runControl()->reportApplicationStop();
|
emit stopped();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TargetRunner
|
// TargetRunner
|
||||||
|
|
||||||
TargetRunner::TargetRunner(RunControl *runControl)
|
TargetRunner::TargetRunner(RunControl *runControl)
|
||||||
: m_runControl(runControl)
|
: m_runControl(runControl)
|
||||||
{
|
{
|
||||||
runControl->setTargetRunner(this);
|
if (runControl)
|
||||||
|
runControl->setTargetRunner(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
RunControl *TargetRunner::runControl() const
|
RunControl *TargetRunner::runControl() const
|
||||||
@@ -993,12 +1167,14 @@ void TargetRunner::appendMessage(const QString &msg, OutputFormat format)
|
|||||||
m_runControl->appendMessage(msg, format);
|
m_runControl->appendMessage(msg, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ToolRunner
|
// ToolRunner
|
||||||
|
|
||||||
ToolRunner::ToolRunner(RunControl *runControl)
|
ToolRunner::ToolRunner(RunControl *runControl)
|
||||||
: m_runControl(runControl)
|
: m_runControl(runControl)
|
||||||
{
|
{
|
||||||
runControl->setToolRunner(this);
|
if (runControl)
|
||||||
|
runControl->setToolRunner(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
RunControl *ToolRunner::runControl() const
|
RunControl *ToolRunner::runControl() const
|
||||||
@@ -1011,6 +1187,7 @@ void ToolRunner::appendMessage(const QString &msg, OutputFormat format)
|
|||||||
m_runControl->appendMessage(msg, format);
|
m_runControl->appendMessage(msg, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// SimpleRunControl
|
// SimpleRunControl
|
||||||
|
|
||||||
SimpleRunControl::SimpleRunControl(RunConfiguration *runConfiguration, Core::Id mode)
|
SimpleRunControl::SimpleRunControl(RunConfiguration *runConfiguration, Core::Id mode)
|
||||||
|
|||||||
@@ -363,15 +363,6 @@ class PROJECTEXPLORER_EXPORT RunControl : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum class State {
|
|
||||||
Initialized,
|
|
||||||
Starting,
|
|
||||||
Running,
|
|
||||||
Stopping,
|
|
||||||
Stopped
|
|
||||||
};
|
|
||||||
Q_ENUM(State)
|
|
||||||
|
|
||||||
RunControl(RunConfiguration *runConfiguration, Core::Id mode);
|
RunControl(RunConfiguration *runConfiguration, Core::Id mode);
|
||||||
~RunControl() override;
|
~RunControl() override;
|
||||||
|
|
||||||
@@ -416,28 +407,32 @@ public:
|
|||||||
virtual void appendMessage(const QString &msg, Utils::OutputFormat format);
|
virtual void appendMessage(const QString &msg, Utils::OutputFormat format);
|
||||||
virtual void bringApplicationToForeground();
|
virtual void bringApplicationToForeground();
|
||||||
|
|
||||||
void reportApplicationStart(); // Call this when the application starts to run
|
|
||||||
void reportApplicationStop(); // Call this when the application has stopped for any reason
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void appendMessageRequested(ProjectExplorer::RunControl *runControl,
|
void appendMessageRequested(ProjectExplorer::RunControl *runControl,
|
||||||
const QString &msg, Utils::OutputFormat format);
|
const QString &msg, Utils::OutputFormat format);
|
||||||
|
void aboutToStart();
|
||||||
void starting();
|
void starting();
|
||||||
void started(QPrivateSignal); // Use reportApplicationStart!
|
void started(); // Use reportApplicationStart!
|
||||||
void finished(QPrivateSignal); // Use reportApplicationStop!
|
void finished(); // Use reportApplicationStop!
|
||||||
void applicationProcessHandleChanged(QPrivateSignal); // Use setApplicationProcessHandle
|
void applicationProcessHandleChanged(QPrivateSignal); // Use setApplicationProcessHandle
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void start();
|
virtual void start();
|
||||||
virtual void stop();
|
virtual void stop();
|
||||||
|
|
||||||
|
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,
|
bool showPromptToStopDialog(const QString &title, const QString &text,
|
||||||
const QString &stopButtonText = QString(),
|
const QString &stopButtonText = QString(),
|
||||||
const QString &cancelButtonText = QString(),
|
const QString &cancelButtonText = QString(),
|
||||||
bool *prompt = nullptr) const;
|
bool *prompt = nullptr) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setState(State state);
|
friend class Internal::RunControlPrivate;
|
||||||
|
friend class TargetRunner;
|
||||||
|
friend class ToolRunner;
|
||||||
|
|
||||||
void bringApplicationToForegroundInternal();
|
void bringApplicationToForegroundInternal();
|
||||||
Internal::RunControlPrivate *d;
|
Internal::RunControlPrivate *d;
|
||||||
};
|
};
|
||||||
@@ -448,14 +443,23 @@ private:
|
|||||||
|
|
||||||
class PROJECTEXPLORER_EXPORT TargetRunner : public QObject
|
class PROJECTEXPLORER_EXPORT TargetRunner : public QObject
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit TargetRunner(RunControl *runControl);
|
explicit TargetRunner(RunControl *runControl);
|
||||||
|
|
||||||
RunControl *runControl() const;
|
RunControl *runControl() const;
|
||||||
void appendMessage(const QString &msg, Utils::OutputFormat format);
|
void appendMessage(const QString &msg, Utils::OutputFormat format);
|
||||||
|
|
||||||
virtual void start() {}
|
virtual void prepare() { emit prepared(); }
|
||||||
virtual void stop() {}
|
virtual void start() { emit started(); }
|
||||||
|
virtual void stop() { emit stopped(); }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void prepared();
|
||||||
|
void started();
|
||||||
|
void stopped();
|
||||||
|
void failed(const QString &msg = QString());
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPointer<RunControl> m_runControl;
|
QPointer<RunControl> m_runControl;
|
||||||
@@ -467,12 +471,24 @@ private:
|
|||||||
|
|
||||||
class PROJECTEXPLORER_EXPORT ToolRunner : public QObject
|
class PROJECTEXPLORER_EXPORT ToolRunner : public QObject
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ToolRunner(RunControl *runControl);
|
explicit ToolRunner(RunControl *runControl);
|
||||||
|
|
||||||
RunControl *runControl() const;
|
RunControl *runControl() const;
|
||||||
void appendMessage(const QString &msg, Utils::OutputFormat format);
|
void appendMessage(const QString &msg, Utils::OutputFormat format);
|
||||||
|
|
||||||
|
virtual void prepare() { emit prepared(); }
|
||||||
|
virtual void start() { emit started(); }
|
||||||
|
virtual void stop() { emit stopped(); }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void prepared();
|
||||||
|
void started();
|
||||||
|
void stopped();
|
||||||
|
void failed(const QString &msg = QString());
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPointer<RunControl> m_runControl;
|
QPointer<RunControl> m_runControl;
|
||||||
};
|
};
|
||||||
@@ -487,14 +503,12 @@ class PROJECTEXPLORER_EXPORT SimpleTargetRunner : public TargetRunner
|
|||||||
public:
|
public:
|
||||||
explicit SimpleTargetRunner(RunControl *runControl);
|
explicit SimpleTargetRunner(RunControl *runControl);
|
||||||
|
|
||||||
|
private:
|
||||||
void start() override;
|
void start() override;
|
||||||
void stop() override;
|
void stop() override;
|
||||||
|
|
||||||
virtual void onProcessStarted();
|
void onProcessStarted();
|
||||||
virtual void onProcessFinished(int exitCode, QProcess::ExitStatus status);
|
void onProcessFinished(int exitCode, QProcess::ExitStatus status);
|
||||||
|
|
||||||
private:
|
|
||||||
void setFinished();
|
|
||||||
|
|
||||||
ApplicationLauncher m_launcher;
|
ApplicationLauncher m_launcher;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user