ProjectExplorer: Extend centralized state handling

Add some customization hooks to make tools aware of target errors
and vice versa.

Change-Id: I4d815087297a3fa1d1d6d52daeed7c4ae0f624bf
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
hjk
2017-05-02 15:03:56 +02:00
parent 9ee0cec3bc
commit 5d8d3fbdc7
6 changed files with 187 additions and 30 deletions

View File

@@ -343,7 +343,7 @@ public:
bool isMasterEngine() const { return m_engine->isMasterEngine(); } bool isMasterEngine() const { return m_engine->isMasterEngine(); }
DebuggerRunTool *runTool() const DebuggerRunTool *runTool() const
{ return m_masterEngine ? m_masterEngine->runTool() : m_runTool.data(); } { return m_masterEngine ? m_masterEngine->runTool() : m_runTool.data(); }
RunControl *runControl() const { return runTool()->runControl(); } RunControl *runControl() const;
void setRemoteSetupState(RemoteSetupState state); void setRemoteSetupState(RemoteSetupState state);
DebuggerEngine *m_engine = nullptr; // Not owned. DebuggerEngine *m_engine = nullptr; // Not owned.
@@ -1147,6 +1147,12 @@ void DebuggerEnginePrivate::doFinishDebugger()
m_runTool->debuggingFinished(); m_runTool->debuggingFinished();
} }
RunControl *DebuggerEnginePrivate::runControl() const
{
DebuggerRunTool *tool = runTool();
return tool ? tool->runControl() : nullptr;
}
void DebuggerEnginePrivate::setRemoteSetupState(RemoteSetupState state) void DebuggerEnginePrivate::setRemoteSetupState(RemoteSetupState state)
{ {
bool allowedTransition = false; bool allowedTransition = false;
@@ -1315,6 +1321,7 @@ void DebuggerEngine::setState(DebuggerState state, bool forced)
showMessage(msg, LogDebug); showMessage(msg, LogDebug);
updateViews(); updateViews();
QTC_ASSERT(runTool(), return);
runTool()->stateChanged(d->m_state); runTool()->stateChanged(d->m_state);
if (isSlaveEngine()) if (isSlaveEngine())
@@ -1542,9 +1549,7 @@ RunControl *DebuggerEngine::runControl() const
DebuggerRunTool *DebuggerEngine::runTool() const DebuggerRunTool *DebuggerEngine::runTool() const
{ {
// if (DebuggerRunControl *rc = d->runControl()) return d->m_masterEngine ? d->m_masterEngine->runTool() : d->m_runTool.data();
// return qobject_cast<DebuggerRunTool *>(rc->toolRunner());
return d->m_runTool;
} }
Terminal *DebuggerEngine::terminal() const Terminal *DebuggerEngine::terminal() const

View File

@@ -182,6 +182,16 @@ void DebuggerRunTool::stop()
m_engine->quitDebugger(); m_engine->quitDebugger();
} }
void DebuggerRunTool::onTargetFailure()
{
if (m_engine->state() == EngineSetupRequested) {
RemoteSetupResult result;
result.success = false;
result.reason = tr("Initial setup failed.");
m_engine->notifyEngineRemoteSetupFinished(result);
}
}
void DebuggerRunTool::debuggingFinished() void DebuggerRunTool::debuggingFinished()
{ {
runControl()->reportApplicationStop(); runControl()->reportApplicationStop();

View File

@@ -56,6 +56,7 @@ public:
void prepare() override; void prepare() override;
void start() override; void start() override;
void stop() override; void stop() override;
void onTargetFailure() override;
void handleFinished(); void handleFinished();

View File

@@ -337,6 +337,7 @@ QmlEngine::QmlEngine(const DebuggerRunParameters &startParameters, DebuggerEngin
QmlEngine::~QmlEngine() QmlEngine::~QmlEngine()
{ {
QObject::disconnect(d->startupMessageFilterConnection);
QSet<IDocument *> documentsToClose; QSet<IDocument *> documentsToClose;
QHash<QString, QWeakPointer<BaseTextEditor> >::iterator iter; QHash<QString, QWeakPointer<BaseTextEditor> >::iterator iter;
@@ -420,6 +421,8 @@ void QmlEngine::beginConnection(Utils::Port port)
QTC_ASSERT(state() == EngineRunRequested, return); QTC_ASSERT(state() == EngineRunRequested, return);
QObject::disconnect(d->startupMessageFilterConnection);
QString host = runParameters().qmlServer.host; QString host = runParameters().qmlServer.host;
// Use localhost as default // Use localhost as default
if (host.isEmpty()) if (host.isEmpty())

View File

@@ -545,10 +545,18 @@ public:
void setState(State state); void setState(State state);
void initiateStart(); void initiateStart();
void onTargetPrepared(); void onTargetPrepared();
void onTargetPrepareFailed(const QString &msg);
void onToolPrepared(); void onToolPrepared();
void onToolPrepareFailed(const QString &msg);
void onTargetStarted(); void onTargetStarted();
void onTargetStartFailed(const QString &msg);
void onToolStarted(); void onToolStarted();
void onToolStartFailed(const QString &msg);
void initiateStop(); void initiateStop();
void onToolStopped(); void onToolStopped();
@@ -558,6 +566,8 @@ public:
void onTargetFailed(const QString &msg); void onTargetFailed(const QString &msg);
void handleFailure(); void handleFailure();
void showError(const QString &msg);
static bool isAllowedTransition(State from, State to); static bool isAllowedTransition(State from, State to);
RunControl *q; RunControl *q;
@@ -619,7 +629,9 @@ RunControl::~RunControl()
#ifdef WITH_JOURNALD #ifdef WITH_JOURNALD
JournaldWatcher::instance()->unsubscribe(this); JournaldWatcher::instance()->unsubscribe(this);
#endif #endif
disconnect();
delete d; delete d;
d = nullptr;
} }
void RunControl::initiateStart() void RunControl::initiateStart()
@@ -657,6 +669,14 @@ void RunControlPrivate::onTargetPrepared()
toolRunner->prepare(); toolRunner->prepare();
} }
void RunControlPrivate::onTargetPrepareFailed(const QString &msg)
{
checkState(State::TargetPreparing);
toolRunner->onTargetFailure();
showError(msg);
setState(State::Stopped);
}
void RunControlPrivate::onToolPrepared() void RunControlPrivate::onToolPrepared()
{ {
checkState(State::ToolPreparing); checkState(State::ToolPreparing);
@@ -664,6 +684,14 @@ void RunControlPrivate::onToolPrepared()
targetRunner->start(); targetRunner->start();
} }
void RunControlPrivate::onToolPrepareFailed(const QString &msg)
{
checkState(State::ToolPreparing);
targetRunner->onToolFailure();
showError(msg);
setState(State::Stopped);
}
void RunControlPrivate::onTargetStarted() void RunControlPrivate::onTargetStarted()
{ {
checkState(State::TargetStarting); checkState(State::TargetStarting);
@@ -671,12 +699,28 @@ void RunControlPrivate::onTargetStarted()
toolRunner->start(); toolRunner->start();
} }
void RunControlPrivate::onTargetStartFailed(const QString &msg)
{
checkState(State::TargetStarting);
toolRunner->onTargetFailure();
showError(msg);
setState(State::Stopped);
}
void RunControlPrivate::onToolStarted() void RunControlPrivate::onToolStarted()
{ {
checkState(State::ToolStarting); checkState(State::ToolStarting);
setState(State::Running); setState(State::Running);
} }
void RunControlPrivate::onToolStartFailed(const QString &msg)
{
checkState(State::ToolStarting);
targetRunner->onToolFailure();
showError(msg);
setState(State::Stopped);
}
void RunControlPrivate::initiateStop() void RunControlPrivate::initiateStop()
{ {
checkState(State::Running); checkState(State::Running);
@@ -697,22 +741,34 @@ void RunControlPrivate::onTargetStopped()
setState(State::Stopped); setState(State::Stopped);
QTC_CHECK(applicationProcessHandle.isValid()); QTC_CHECK(applicationProcessHandle.isValid());
q->setApplicationProcessHandle(Utils::ProcessHandle()); q->setApplicationProcessHandle(Utils::ProcessHandle());
targetRunner->onFinished();
} }
void RunControlPrivate::onTargetFailed(const QString &msg) void RunControlPrivate::onTargetFailed(const QString &msg)
{ {
if (!msg.isEmpty()) if (state == State::TargetPreparing) {
q->appendMessage(msg, ErrorMessageFormat); onTargetPrepareFailed(msg);
} else if (state == State::TargetStarting) {
handleFailure(); onTargetStartFailed(msg);
} else {
showError(msg);
// showError(RunControl::tr("Unexpected state: %1").arg(int(state)));
setState(State::Stopped);
}
} }
void RunControlPrivate::onToolFailed(const QString &msg) void RunControlPrivate::onToolFailed(const QString &msg)
{ {
if (!msg.isEmpty()) if (state == State::ToolPreparing) {
q->appendMessage(msg, ErrorMessageFormat); onToolPrepareFailed(msg);
} else if (state == State::ToolStarting) {
handleFailure(); onToolStartFailed(msg);
} else {
showError(msg);
// showError(RunControl::tr("Unexpected state: %1").arg(int(state)));
setState(State::Stopped);
}
} }
void RunControlPrivate::handleFailure() void RunControlPrivate::handleFailure()
@@ -732,6 +788,12 @@ void RunControlPrivate::handleFailure()
} }
} }
void RunControlPrivate::showError(const QString &msg)
{
if (!msg.isEmpty())
q->appendMessage(msg, ErrorMessageFormat);
}
Utils::OutputFormatter *RunControl::outputFormatter() const Utils::OutputFormatter *RunControl::outputFormatter() const
{ {
return d->outputFormatter; return d->outputFormatter;
@@ -1081,10 +1143,10 @@ 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()) {
reportFailure(RunControl::tr("No executable specified.")); reportStartFailed(RunControl::tr("No executable specified."));
} else if (!QFileInfo::exists(executable)) { } else if (!QFileInfo::exists(executable)) {
reportFailure(RunControl::tr("Executable %1 does not exist.") reportStartFailed(RunControl::tr("Executable %1 does not exist.")
.arg(QDir::toNativeSeparators(executable))); .arg(QDir::toNativeSeparators(executable)));
} 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);
@@ -1170,12 +1232,37 @@ IDevice::ConstPtr TargetRunner::device() const
return m_runControl->device(); return m_runControl->device();
} }
void TargetRunner::prepare()
{
reportPrepared(); // By default nothing to do, all is fine.
}
void TargetRunner::reportPrepareFailed(const QString &msg)
{
m_runControl->d->onTargetPrepareFailed(msg);
}
void TargetRunner::reportPrepared() void TargetRunner::reportPrepared()
{ {
QTC_ASSERT(m_runControl, return); QTC_ASSERT(m_runControl, return);
m_runControl->d->onTargetPrepared(); m_runControl->d->onTargetPrepared();
} }
void TargetRunner::start()
{
reportStarted();
}
void TargetRunner::reportStartFailed(const QString &msg)
{
m_runControl->d->onTargetStartFailed(msg);
}
void TargetRunner::stop()
{
reportStopped(); // By default all is fine.
}
void TargetRunner::reportStarted() void TargetRunner::reportStarted()
{ {
QTC_ASSERT(m_runControl, return); QTC_ASSERT(m_runControl, return);
@@ -1194,7 +1281,6 @@ void TargetRunner::reportFailure(const QString &msg)
m_runControl->d->onTargetFailed(msg); m_runControl->d->onTargetFailed(msg);
} }
// ToolRunner // ToolRunner
ToolRunner::ToolRunner(RunControl *runControl) ToolRunner::ToolRunner(RunControl *runControl)
@@ -1219,16 +1305,45 @@ IDevice::ConstPtr ToolRunner::device() const
return m_runControl->device(); return m_runControl->device();
} }
void ToolRunner::prepare()
{
reportPrepared();
}
void ToolRunner::reportPrepared() void ToolRunner::reportPrepared()
{ {
m_runControl->d->onToolPrepared(); m_runControl->d->onToolPrepared();
} }
void ToolRunner::start()
{
reportStarted();
}
void ToolRunner::reportStartFailed(const QString &msg)
{
QTC_CHECK(m_runControl->d->state == RunControlPrivate::State::ToolStarting);
m_runControl->d->targetRunner->onToolFailure();
reportFailure(msg);
}
void ToolRunner::reportStarted() void ToolRunner::reportStarted()
{ {
m_runControl->d->onToolStarted(); m_runControl->d->onToolStarted();
} }
void ToolRunner::stop()
{
reportStopped();
}
void ToolRunner::reportStopFailed(const QString &msg)
{
QTC_CHECK(m_runControl->d->state == RunControlPrivate::State::ToolStopping);
m_runControl->d->targetRunner->onToolFailure();
reportFailure(msg);
}
void ToolRunner::reportStopped() void ToolRunner::reportStopped()
{ {
onStop(); onStop();

View File

@@ -459,18 +459,30 @@ public:
void appendMessage(const QString &msg, Utils::OutputFormat format); void appendMessage(const QString &msg, Utils::OutputFormat format);
IDevice::ConstPtr device() const; IDevice::ConstPtr device() const;
virtual void prepare() { reportPrepared(); } // Preparation phase.
virtual void start() { reportStarted(); } virtual void prepare(); // Initiate setup. Needs to report result.
virtual void stop() { reportStopped(); } void reportPrepareFailed(const QString &msg = QString());
virtual void onStop() {}
virtual void onFailure() {}
void reportPrepared(); void reportPrepared();
// Startup phase.
virtual void start(); // Initiates start. Needs to report result.
void reportStartFailed(const QString &msg = QString());
void reportStarted(); void reportStarted();
// Stopping phase.
virtual void stop(); // Initiates stop. Needs to report result.
void reportStopFailed(const QString &msg = QString());
void reportStopped(); void reportStopped();
// Generic error in uncertain state.
void reportFailure(const QString &msg = QString()); void reportFailure(const QString &msg = QString());
// Customization points. No reporting required nor wanted.
virtual void onStop() {}
virtual void onToolFailure() {}
virtual void onTargetFailure() {}
virtual void onFinished() {}
private: private:
QPointer<RunControl> m_runControl; QPointer<RunControl> m_runControl;
}; };
@@ -490,18 +502,29 @@ public:
void appendMessage(const QString &msg, Utils::OutputFormat format); void appendMessage(const QString &msg, Utils::OutputFormat format);
IDevice::ConstPtr device() const; IDevice::ConstPtr device() const;
virtual void prepare() { reportPrepared(); } // Preparation phase.
virtual void start() { reportStarted(); } virtual void prepare(); // Initiates preparation, needs to report success or failure.
virtual void stop() { reportStopped(); } void reportPrepareFailed(const QString &msg = QString());
virtual void onStop() {}
virtual void onFailure() {}
void reportPrepared(); void reportPrepared();
// Start phase.
virtual void start();
void reportStartFailed(const QString &msg = QString());
void reportStarted(); void reportStarted();
// Stop phase.
virtual void stop();
void reportStopFailed(const QString &msg = QString());
void reportStopped(); void reportStopped();
// Generic error in uncertain state.
void reportFailure(const QString &msg = QString()); void reportFailure(const QString &msg = QString());
// Customization points. No reporting required nor wanted.
virtual void onStop() {}
virtual void onToolFailure() {}
virtual void onTargetFailure() {}
private: private:
QPointer<RunControl> m_runControl; QPointer<RunControl> m_runControl;
}; };