From 4790548216a9a98fbd894a912e307c65ff1e81e0 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Mon, 15 Nov 2010 17:09:28 +0100 Subject: [PATCH] QmlDebugger: Refactored QmlEngine and QmlCppEngine Reviewed by: hjk --- src/libs/qmljsdebugclient/qdeclarativedebug.cpp | 5 + .../qmljsdebugclient/qdeclarativedebugclient.cpp | 43 +- .../qmljsdebugclient/qdeclarativedebugclient_p.h | 2 +- src/plugins/debugger/debuggerengine.cpp | 6 +- src/plugins/debugger/qml/qmlcppengine.cpp | 439 +++++++++------------ src/plugins/debugger/qml/qmlcppengine.h | 7 +- src/plugins/debugger/qml/qmlengine.cpp | 144 +++---- src/plugins/debugger/qml/qmlengine.h | 10 +- 8 files changed, 292 insertions(+), 364 deletions(-) diff --git a/src/libs/qmljsdebugclient/qdeclarativedebug.cpp b/src/libs/qmljsdebugclient/qdeclarativedebug.cpp index e3b653008e..e36cd0082e 100644 --- a/src/libs/qmljsdebugclient/qdeclarativedebug.cpp +++ b/src/libs/qmljsdebugclient/qdeclarativedebug.cpp @@ -49,6 +49,7 @@ class QDeclarativeEngineDebugClient : public QDeclarativeDebugClient { public: QDeclarativeEngineDebugClient(QDeclarativeDebugConnection *client, QDeclarativeEngineDebugPrivate *p); + ~QDeclarativeEngineDebugClient(); protected: virtual void statusChanged(Status status); @@ -96,6 +97,10 @@ QDeclarativeEngineDebugClient::QDeclarativeEngineDebugClient(QDeclarativeDebugCo { } +QDeclarativeEngineDebugClient::~QDeclarativeEngineDebugClient() +{ +} + void QDeclarativeEngineDebugClient::statusChanged(Status status) { if (priv) diff --git a/src/libs/qmljsdebugclient/qdeclarativedebugclient.cpp b/src/libs/qmljsdebugclient/qdeclarativedebugclient.cpp index a78575a54c..4a54541c06 100644 --- a/src/libs/qmljsdebugclient/qdeclarativedebugclient.cpp +++ b/src/libs/qmljsdebugclient/qdeclarativedebugclient.cpp @@ -59,7 +59,7 @@ public: QDeclarativeDebugClientPrivate(); QString name; - QDeclarativeDebugConnection *client; + QDeclarativeDebugConnection *connection; }; class QDeclarativeDebugConnectionPrivate : public QObject @@ -199,7 +199,7 @@ QDeclarativeDebugConnection::~QDeclarativeDebugConnection() { QHash::iterator iter = d->plugins.begin(); for (; iter != d->plugins.end(); ++iter) { - iter.value()->d_func()->client = 0; + iter.value()->d_func()->connection = 0; iter.value()->statusChanged(QDeclarativeDebugClient::NotConnected); } } @@ -210,50 +210,54 @@ bool QDeclarativeDebugConnection::isConnected() const } QDeclarativeDebugClientPrivate::QDeclarativeDebugClientPrivate() -: client(0) +: connection(0) { } QDeclarativeDebugClient::QDeclarativeDebugClient(const QString &name, QDeclarativeDebugConnection *parent) -: QObject(parent), d(new QDeclarativeDebugClientPrivate()) +: QObject(parent), d_ptr(new QDeclarativeDebugClientPrivate()) { + Q_D(QDeclarativeDebugClient); d->name = name; - d->client = parent; + d->connection = parent; - if (!d->client) + if (!d->connection) return; - if (d->client->d->plugins.contains(name)) { + if (d->connection->d->plugins.contains(name)) { qWarning() << "QDeclarativeDebugClient: Conflicting plugin name" << name; - d->client = 0; + d->connection = 0; } else { - d->client->d->plugins.insert(name, this); - d->client->d->advertisePlugins(); + d->connection->d->plugins.insert(name, this); + d->connection->d->advertisePlugins(); } } QDeclarativeDebugClient::~QDeclarativeDebugClient() { - if (d->client && d->client->d) { - d->client->d->plugins.remove(d->name); - d->client->d->advertisePlugins(); + Q_D(QDeclarativeDebugClient); + if (d->connection && d->connection->d) { + d->connection->d->plugins.remove(d->name); + d->connection->d->advertisePlugins(); } } QString QDeclarativeDebugClient::name() const { + Q_D(const QDeclarativeDebugClient); return d->name; } QDeclarativeDebugClient::Status QDeclarativeDebugClient::status() const { - if (!d->client - || !d->client->isConnected() - || !d->client->d->gotHello) + Q_D(const QDeclarativeDebugClient); + if (!d->connection + || !d->connection->isConnected() + || !d->connection->d->gotHello) return NotConnected; - if (d->client->d->serverPlugins.contains(d->name)) + if (d->connection->d->serverPlugins.contains(d->name)) return Enabled; return Unavailable; @@ -261,13 +265,14 @@ QDeclarativeDebugClient::Status QDeclarativeDebugClient::status() const void QDeclarativeDebugClient::sendMessage(const QByteArray &message) { + Q_D(QDeclarativeDebugClient); if (status() != Enabled) return; QPacket pack; pack << d->name << message; - d->client->d->protocol->send(pack); - d->client->flush(); + d->connection->d->protocol->send(pack); + d->connection->flush(); } void QDeclarativeDebugClient::statusChanged(Status) diff --git a/src/libs/qmljsdebugclient/qdeclarativedebugclient_p.h b/src/libs/qmljsdebugclient/qdeclarativedebugclient_p.h index f29e58a1b2..2ae8bc8e79 100644 --- a/src/libs/qmljsdebugclient/qdeclarativedebugclient_p.h +++ b/src/libs/qmljsdebugclient/qdeclarativedebugclient_p.h @@ -90,7 +90,7 @@ protected: private: friend class QDeclarativeDebugConnection; friend class QDeclarativeDebugConnectionPrivate; - QScopedPointer d; + QScopedPointer d_ptr; }; } diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index f706146117..a85538a8e4 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -758,7 +758,7 @@ void DebuggerEngine::notifyEngineRunFailed() d->m_progress.reportCanceled(); d->m_progress.reportFinished(); setState(EngineRunFailed); - d->queueShutdownEngine(); + d->queueShutdownInferior(); } void DebuggerEngine::notifyEngineRunAndInferiorRunOk() @@ -980,8 +980,8 @@ void DebuggerEngine::notifyInferiorExited() void DebuggerEngine::setState(DebuggerState state, bool forced) { - //qDebug() << "STATUS CHANGE: FROM " << stateName(d->m_state) - // << " TO " << stateName(state); + qDebug() << "STATUS CHANGE: FROM " << stateName(d->m_state) + << " TO " << stateName(state); DebuggerState oldState = d->m_state; d->m_state = state; diff --git a/src/plugins/debugger/qml/qmlcppengine.cpp b/src/plugins/debugger/qml/qmlcppengine.cpp index 74c788a4c4..9b8bde92e9 100644 --- a/src/plugins/debugger/qml/qmlcppengine.cpp +++ b/src/plugins/debugger/qml/qmlcppengine.cpp @@ -30,27 +30,24 @@ DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &sp) } // namespace Internal -struct QmlCppEnginePrivate -{ +class QmlCppEnginePrivate { +public: QmlCppEnginePrivate(); + ~QmlCppEnginePrivate() {} + friend class QmlCppEngine; +private: QmlEngine *m_qmlEngine; DebuggerEngine *m_cppEngine; DebuggerEngine *m_activeEngine; - bool m_shutdownOk; - bool m_shutdownDeferred; - bool m_shutdownDone; - bool m_isInitialStartup; + DebuggerState m_errorState; }; -QmlCppEnginePrivate::QmlCppEnginePrivate() - : m_qmlEngine(0) - , m_cppEngine(0) - , m_activeEngine(0) - , m_shutdownOk(true) - , m_shutdownDeferred(false) - , m_shutdownDone(false) - , m_isInitialStartup(true) +QmlCppEnginePrivate::QmlCppEnginePrivate() : + m_qmlEngine(0), + m_cppEngine(0), + m_activeEngine(0), + m_errorState(InferiorRunOk) { } @@ -58,7 +55,6 @@ QmlCppEngine::QmlCppEngine(const DebuggerStartParameters &sp) : DebuggerEngine(sp), d(new QmlCppEnginePrivate) { d->m_qmlEngine = qobject_cast(Internal::createQmlEngine(sp)); - d->m_qmlEngine->setAttachToRunningExternalApp(true); if (startParameters().cppEngineType == GdbEngineType) { d->m_cppEngine = Internal::createGdbEngine(sp); @@ -87,10 +83,10 @@ QmlCppEngine::QmlCppEngine(const DebuggerStartParameters &sp) QmlCppEngine::~QmlCppEngine() { - delete d->m_qmlEngine; - d->m_qmlEngine = 0; - delete d->m_cppEngine; - d->m_cppEngine = 0; + if (d->m_qmlEngine) + delete d->m_qmlEngine; + if (d->m_cppEngine) + delete d->m_cppEngine; } void QmlCppEngine::editorChanged(Core::IEditor *editor) @@ -128,6 +124,15 @@ void QmlCppEngine::setActiveEngine(DebuggerLanguage language) } } +DebuggerLanguage QmlCppEngine::activeEngine() const +{ + if (d->m_activeEngine == d->m_cppEngine) + return CppLanguage; + if (d->m_activeEngine == d->m_qmlEngine) + return QmlLanguage; + return AnyLanguage; +} + void QmlCppEngine::setToolTipExpression(const QPoint & mousePos, TextEditor::ITextEditor *editor, int cursorPos) { @@ -332,17 +337,31 @@ void QmlCppEngine::executeReturn() void QmlCppEngine::continueInferior() { - d->m_activeEngine->continueInferior(); + if (d->m_activeEngine->state() == InferiorStopOk) { + d->m_activeEngine->continueInferior(); + } else { + notifyInferiorRunRequested(); + } } void QmlCppEngine::interruptInferior() { - d->m_activeEngine->interruptInferior(); + if (d->m_activeEngine->state() == InferiorRunOk) { + d->m_activeEngine->requestInterruptInferior(); + } else { + if (d->m_activeEngine->state() == InferiorStopOk && (!checkErrorState(InferiorStopFailed))) { + notifyInferiorStopOk(); + } + } } void QmlCppEngine::requestInterruptInferior() { - d->m_activeEngine->requestInterruptInferior(); + DebuggerEngine::requestInterruptInferior(); + + if (d->m_activeEngine->state() == InferiorRunOk) { + d->m_activeEngine->requestInterruptInferior(); + } } void QmlCppEngine::executeRunToLine(const QString &fileName, int lineNumber) @@ -375,6 +394,50 @@ void QmlCppEngine::frameDown() d->m_activeEngine->frameDown(); } +///////////////////////////////////////////////////////// + +bool QmlCppEngine::checkErrorState(const DebuggerState stateToCheck) +{ + if (d->m_errorState != stateToCheck) + return false; + + // reset state ( so that more than one error can accumulate over time ) + d->m_errorState = InferiorRunOk; + switch (stateToCheck) { + case InferiorRunOk: + // nothing to do + break; + case EngineRunFailed: + notifyEngineRunFailed(); + break; + case EngineSetupFailed: + notifyEngineSetupFailed(); + break; + case EngineShutdownFailed: + notifyEngineShutdownFailed(); + break; + case InferiorSetupFailed: + notifyInferiorSetupFailed(); + break; + case InferiorRunFailed: + notifyInferiorRunFailed(); + break; + case InferiorUnrunnable: + notifyInferiorUnrunnable(); + break; + case InferiorStopFailed: + notifyInferiorStopFailed(); + break; + case InferiorShutdownFailed: + notifyInferiorShutdownFailed(); + break; + default: + // unexpected + break; + } + return true; +} + void QmlCppEngine::notifyInferiorRunOk() { DebuggerEngine::notifyInferiorRunOk(); @@ -390,56 +453,68 @@ void QmlCppEngine::setupEngine() void QmlCppEngine::setupInferior() { - // called through notifyEngineSetupOk + if (!checkErrorState(InferiorSetupFailed)) { + notifyInferiorSetupOk(); + } } void QmlCppEngine::runEngine() { - // should never happen - showMessage(QString(Q_FUNC_INFO), LogError); + if (!checkErrorState(EngineRunFailed)) { + if (d->m_errorState == InferiorRunOk) { + switch (d->m_activeEngine->state()) { + case InferiorRunOk: + notifyEngineRunAndInferiorRunOk(); + break; + case InferiorStopOk: + notifyEngineRunAndInferiorStopOk(); + break; + default: // not supported? + notifyEngineRunFailed(); + break; + } + } else { + notifyEngineRunFailed(); + } + } } void QmlCppEngine::shutdownInferior() { - // user wants to stop inferior: always use cpp engine for this. - if (d->m_activeEngine == d->m_qmlEngine) { - d->m_activeEngine = d->m_cppEngine; - - // we end up in this state after trying to shut down while debugging qml. - // b/c qml does not shutdown by itself, restore previous state and continue. - if (d->m_qmlEngine->state() == InferiorShutdownRequested) { - d->m_qmlEngine->setState(InferiorStopOk, true); - } - - if (d->m_qmlEngine->state() == InferiorStopOk) { - d->m_qmlEngine->continueInferior(); + if (!checkErrorState(InferiorShutdownFailed)) { + if (d->m_cppEngine->state() == InferiorStopOk) { + d->m_cppEngine->shutdownInferior(); + } else { + notifyInferiorShutdownOk(); } } - if (d->m_cppEngine->state() == InferiorRunOk) { - // first interrupt c++ engine; when done, we can shutdown. - d->m_shutdownDeferred = true; - d->m_cppEngine->requestInterruptInferior(); - } - if (!d->m_shutdownDeferred) - d->m_cppEngine->shutdownInferior(); } -void QmlCppEngine::shutdownEngine() +void QmlCppEngine::initEngineShutdown() { - d->m_cppEngine->shutdownEngine(); - d->m_qmlEngine->shutdownEngineAsSlave(); - notifyEngineShutdownOk(); + if (d->m_qmlEngine->state() != DebuggerFinished) { + d->m_qmlEngine->quitDebugger(); + } else + if (d->m_cppEngine->state() != DebuggerFinished) { + d->m_cppEngine->quitDebugger(); + } else + if (state() == EngineSetupRequested) { + if (!checkErrorState(EngineSetupFailed)) { + notifyEngineSetupOk(); + } + } else + if (state() == InferiorStopRequested) { + checkErrorState(InferiorStopFailed); + } else { + quitDebugger(); + } } -void QmlCppEngine::finishDebugger() +void QmlCppEngine::shutdownEngine() { - if (!d->m_shutdownDone) { - d->m_shutdownDone = true; - if (d->m_shutdownOk) { - notifyEngineShutdownOk(); - } else { - notifyEngineShutdownFailed(); - } + if (!checkErrorState(EngineShutdownFailed)) { + showStatusMessage(tr("Debugging finished")); + notifyEngineShutdownOk(); } } @@ -450,227 +525,103 @@ void QmlCppEngine::setupSlaveEngineOnTimer() void QmlCppEngine::setupSlaveEngine() { - if (state() == InferiorRunRequested) + if (d->m_qmlEngine->state() == DebuggerNotReady) d->m_qmlEngine->startDebugger(runControl()); } void QmlCppEngine::masterEngineStateChanged(const DebuggerState &newState) { - //qDebug() << "gdb state set to" << newState; - - switch(newState) { - case EngineSetupRequested: - // go through this state - break; - - case EngineSetupFailed: - notifyEngineSetupFailed(); - break; - - case EngineSetupOk: - notifyEngineSetupOk(); - break; - - case InferiorSetupRequested: - // go through this state - break; - - case InferiorSetupFailed: - notifyInferiorSetupFailed(); - break; - - case EngineRunRequested: - setState(newState); - break; - - case EngineRunFailed: - notifyEngineRunFailed(); - break; + if (newState == InferiorStopOk) { + setActiveEngine(CppLanguage); + } + engineStateChanged(newState); +} - case InferiorUnrunnable: - setState(newState); - break; +void QmlCppEngine::slaveEngineStateChanged(const DebuggerState &newState) +{ + if (newState == InferiorStopOk) { + setActiveEngine(QmlLanguage); + } + engineStateChanged(newState); +} - case InferiorRunRequested: - setState(newState); - break; +void QmlCppEngine::engineStateChanged(const DebuggerState &newState) +{ + switch (newState) { case InferiorRunOk: + // startup? if (d->m_qmlEngine->state() == DebuggerNotReady) { - if (d->m_isInitialStartup) { - d->m_isInitialStartup = false; - setupSlaveEngineOnTimer(); - } else { - setupSlaveEngine(); - } - } else { + setupSlaveEngine(); + } else + if (d->m_cppEngine->state() == DebuggerNotReady) { + setupEngine(); + } else + if (state() == EngineSetupRequested) { + notifyEngineSetupOk(); + } else + // breakpoint? + if (state() == InferiorStopOk) { + continueInferior(); + } else + if (state() == InferiorStopRequested) { + checkErrorState(InferiorStopFailed); + } else + if (state() == InferiorRunRequested && (!checkErrorState(InferiorRunFailed)) && (!checkErrorState(InferiorUnrunnable))) { notifyInferiorRunOk(); } break; - case InferiorRunFailed: - notifyInferiorRunFailed(); + case InferiorRunRequested: + // follow the inferior + if (state() == InferiorStopOk && checkErrorState(InferiorRunOk)) { + continueInferior(); + } break; case InferiorStopRequested: - if (state() == InferiorRunRequested) { - // if stopping on startup, move on to normal state - // and go forward. Also, stop connection and continue later if needed. - d->m_qmlEngine->pauseConnection(); - setState(EngineRunRequested, true); - notifyEngineRunAndInferiorRunOk(); - setState(newState); - } else { - setState(newState); + // follow the inferior + if (state() == InferiorRunOk && checkErrorState(InferiorRunOk)) { + requestInterruptInferior(); } break; case InferiorStopOk: - // debugger can stop while qml connection is not made yet, so we can - // end up in an illegal state transition here. - if (state() == InferiorStopRequested - || state() == InferiorRunFailed) - { - setState(newState); - } else if (state() == InferiorRunOk) { - // if we break on CPP side while running & engine is QML, switch. - if (d->m_activeEngine == d->m_qmlEngine) { - setActiveEngine(CppLanguage); + // check breakpoints + if (state() == InferiorRunRequested) { + checkErrorState(InferiorRunFailed); + } else + if (checkErrorState(InferiorRunOk)) { + if (state() == InferiorRunOk) { + requestInterruptInferior(); + } else + if (state() == InferiorStopRequested) { + interruptInferior(); } - setState(newState); - } else if (state() == InferiorRunRequested) { - setState(newState, true); - } - if (d->m_shutdownDeferred) { - d->m_activeEngine = d->m_cppEngine; - d->m_shutdownDeferred = false; - shutdownInferior(); } break; + case EngineRunFailed: + case EngineSetupFailed: + case EngineShutdownFailed: + case InferiorSetupFailed: + case InferiorRunFailed: + case InferiorUnrunnable: case InferiorStopFailed: - setState(newState); - if (d->m_shutdownDeferred) { - d->m_activeEngine = d->m_cppEngine; - d->m_shutdownDeferred = false; - shutdownInferior(); - } - break; - - // here, we shut down the qml engine first. - // but due to everything being asynchronous, we cannot guarantee - // that it is shut down completely before gdb engine is shut down. - case InferiorShutdownRequested: - if (d->m_activeEngine == d->m_qmlEngine) { - d->m_activeEngine = d->m_cppEngine; - } - - d->m_qmlEngine->shutdownInferiorAsSlave(); - setState(newState); - break; - - case InferiorShutdownOk: - setState(newState); - d->m_qmlEngine->shutdownEngineAsSlave(); - break; - case InferiorShutdownFailed: - setState(newState); - d->m_qmlEngine->shutdownEngineAsSlave(); - break; - - case EngineShutdownRequested: - setState(newState); - break; - - case EngineShutdownOk: - finishDebugger(); - break; - - case EngineShutdownFailed: - d->m_shutdownOk = false; - finishDebugger(); - break; - - default: - break; - } -} - -void QmlCppEngine::slaveEngineStateChanged(const DebuggerState &newState) -{ - //qDebug() << " qml engine changed to" << newState; - - if (d->m_activeEngine == d->m_qmlEngine) { - handleSlaveEngineStateChangeAsActive(newState); - } else { - handleSlaveEngineStateChange(newState); - } -} - -void QmlCppEngine::handleSlaveEngineStateChange(const DebuggerState &newState) -{ - switch(newState) { - case InferiorRunOk: - if (state() == InferiorRunRequested) { - // force state back so that the notification will succeed on init - setState(EngineRunRequested, true); - notifyEngineRunAndInferiorRunOk(); - } else { - // we have to manually override state with current one, because - // otherwise we'll have debugger controls in inconsistent state. - setState(state(), true); + if (d->m_errorState == InferiorRunOk) { + d->m_errorState = newState; } - break; - case InferiorStopOk: - if (state() == InferiorRunOk) { - // breakpoint was hit while running the app; change the active engine. - setActiveEngine(QmlLanguage); - setState(InferiorStopOk); + case InferiorShutdownRequested: + if (activeEngine() == QmlLanguage) { + setActiveEngine(CppLanguage); } break; - case InferiorRunFailed: - notifyInferiorRunFailed(); - break; - - case EngineShutdownFailed: - d->m_shutdownOk = false; - break; - - default: - // reset wrapper engine state to current state. - setState(state(), true); - break; - } -} - -void QmlCppEngine::handleSlaveEngineStateChangeAsActive(const DebuggerState &newState) -{ - switch(newState) { - case InferiorRunRequested: - setState(newState); - break; - - case InferiorRunOk: - setState(newState); - break; - - case InferiorStopOk: - setState(newState); - break; - - case InferiorRunFailed: - notifyInferiorRunFailed(); - break; - - case InferiorShutdownRequested: - if (d->m_cppEngine->state() == InferiorRunOk) { - // occurs when user presses stop button from debugger UI. - shutdownInferior(); - } + case DebuggerFinished: + initEngineShutdown(); break; default: diff --git a/src/plugins/debugger/qml/qmlcppengine.h b/src/plugins/debugger/qml/qmlcppengine.h index 9bb063adde..7c3ea0a9ac 100644 --- a/src/plugins/debugger/qml/qmlcppengine.h +++ b/src/plugins/debugger/qml/qmlcppengine.h @@ -20,6 +20,7 @@ public: explicit QmlCppEngine(const DebuggerStartParameters &sp); virtual ~QmlCppEngine(); + DebuggerLanguage activeEngine() const; void setActiveEngine(DebuggerLanguage language); virtual void setToolTipExpression(const QPoint &mousePos, @@ -107,9 +108,9 @@ private slots: private: void setupSlaveEngineOnTimer(); - void finishDebugger(); - void handleSlaveEngineStateChange(const DebuggerState &newState); - void handleSlaveEngineStateChangeAsActive(const DebuggerState &newState); + void initEngineShutdown(); + bool checkErrorState(const DebuggerState stateToCheck); + void engineStateChanged(const DebuggerState &newState); private: QScopedPointer d; diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index d297bfd539..00382be3b4 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -143,26 +143,23 @@ static QDataStream &operator>>(QDataStream &s, StackFrame &frame) } // namespace Internal + using namespace Internal; -struct QmlEnginePrivate -{ +class QmlEnginePrivate { +public: explicit QmlEnginePrivate(QmlEngine *q); + friend class QmlEngine; +private: int m_ping; QmlAdapter *m_adapter; ProjectExplorer::ApplicationLauncher m_applicationLauncher; - bool m_addedAdapterToObjectPool; - bool m_attachToRunningExternalApp; - bool m_hasShutdown; }; -QmlEnginePrivate::QmlEnginePrivate(QmlEngine *q) - : m_ping(0) - , m_adapter(new QmlAdapter(q)) - , m_addedAdapterToObjectPool(false) - , m_attachToRunningExternalApp(false) - , m_hasShutdown(false) +QmlEnginePrivate::QmlEnginePrivate(QmlEngine *q) : + m_ping(0) +, m_adapter(new QmlAdapter(q)) { } @@ -180,16 +177,7 @@ QmlEngine::QmlEngine(const DebuggerStartParameters &startParameters) QmlEngine::~QmlEngine() { -} - -void QmlEngine::setAttachToRunningExternalApp(bool value) -{ - d->m_attachToRunningExternalApp = value; -} - -void QmlEngine::pauseConnection() -{ - d->m_adapter->pauseConnection(); + delete d->m_adapter; } void QmlEngine::gotoLocation(const QString &fileName, int lineNumber, bool setMarker) @@ -242,11 +230,11 @@ void QmlEngine::connectionEstablished() ExtensionSystem::PluginManager::instance(); pluginManager->addObject(d->m_adapter); pluginManager->addObject(this); - d->m_addedAdapterToObjectPool = true; showMessage(tr("QML Debugger connected."), StatusBar); notifyEngineRunAndInferiorRunOk(); + } void QmlEngine::connectionStartupFailed() @@ -271,18 +259,51 @@ void QmlEngine::serviceConnectionError(const QString &serviceName) .arg(serviceName), StatusBar); } +void QmlEngine::pauseConnection() +{ + d->m_adapter->pauseConnection(); +} + +void QmlEngine::closeConnection() +{ + ExtensionSystem::PluginManager *pluginManager = ExtensionSystem::PluginManager::instance(); + if (pluginManager->allObjects().contains(this)) { + disconnect(d->m_adapter, SIGNAL(connectionStartupFailed()), this, SLOT(connectionStartupFailed())); + d->m_adapter->closeConnection(); + + pluginManager->removeObject(d->m_adapter); + pluginManager->removeObject(this); + } +} + + void QmlEngine::runEngine() { QTC_ASSERT(state() == EngineRunRequested, qDebug() << state()); - if (!d->m_attachToRunningExternalApp) { + if (!isSlaveEngine()) { + startApplicationLauncher(); + } + + d->m_adapter->beginConnection(); + showMessage(tr("QML Debugger connecting..."), StatusBar); +} + +void QmlEngine::startApplicationLauncher() +{ + if (!d->m_applicationLauncher.isRunning()) { d->m_applicationLauncher.start(ProjectExplorer::ApplicationLauncher::Gui, startParameters().executable, startParameters().processArgs); } +} - d->m_adapter->beginConnection(); - showMessage(tr("QML Debugger connecting..."), StatusBar); +void QmlEngine::stopApplicationLauncher() +{ + if (d->m_applicationLauncher.isRunning()) { + disconnect(&d->m_applicationLauncher, SIGNAL(processExited(int)), this, SLOT(disconnected())); + d->m_applicationLauncher.stop(); + } } void QmlEngine::handleRemoteSetupDone(int port) @@ -299,82 +320,25 @@ void QmlEngine::handleRemoteSetupFailed(const QString &message) notifyInferiorSetupFailed(); } -void QmlEngine::shutdownInferiorAsSlave() -{ - resetLocation(); - - // This can be issued in almost any state. We assume, though, - // that at this point of time the inferior is not running anymore, - // even if stop notification were not issued or got lost. - if (state() == InferiorRunOk) { - setState(InferiorStopRequested); - setState(InferiorStopOk); - setState(InferiorShutdownRequested); - setState(InferiorShutdownOk); - } else { - // force - setState(InferiorShutdownRequested, true); - setState(InferiorShutdownOk); - } -} - -void QmlEngine::shutdownEngineAsSlave() -{ - if (d->m_hasShutdown) - return; - - disconnect(d->m_adapter, SIGNAL(connectionStartupFailed()), - this, SLOT(connectionStartupFailed())); - d->m_adapter->closeConnection(); - - if (d->m_addedAdapterToObjectPool) { - ExtensionSystem::PluginManager *pluginManager = - ExtensionSystem::PluginManager::instance(); - pluginManager->removeObject(d->m_adapter); - pluginManager->removeObject(this); - } - - if (d->m_attachToRunningExternalApp) { - setState(EngineShutdownRequested, true); - setState(EngineShutdownOk, true); - setState(DebuggerFinished, true); - } else { - if (d->m_applicationLauncher.isRunning()) { - // should only happen if engine is ill - disconnect(&d->m_applicationLauncher, SIGNAL(processExited(int)), - this, SLOT(disconnected())); - d->m_applicationLauncher.stop(); - } - } - d->m_hasShutdown = true; -} - void QmlEngine::shutdownInferior() { - // don't do normal shutdown if running as slave engine - if (d->m_attachToRunningExternalApp) - return; - - QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state()); - if (!d->m_applicationLauncher.isRunning()) { - showMessage(tr("Trying to stop while process is no longer running."), LogError); - } else { - disconnect(&d->m_applicationLauncher, SIGNAL(processExited(int)), - this, SLOT(disconnected())); - if (!d->m_attachToRunningExternalApp) - d->m_applicationLauncher.stop(); + if (isSlaveEngine()) { + resetLocation(); } + stopApplicationLauncher(); notifyInferiorShutdownOk(); } void QmlEngine::shutdownEngine() { - QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state()); + closeConnection(); - shutdownEngineAsSlave(); + // double check (ill engine?): + stopApplicationLauncher(); notifyEngineShutdownOk(); - showMessage(QString(), StatusBar); + if (!isSlaveEngine()) + showMessage(QString(), StatusBar); } void QmlEngine::setupEngine() diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h index 3cc949d7d3..d080da6edd 100644 --- a/src/plugins/debugger/qml/qmlengine.h +++ b/src/plugins/debugger/qml/qmlengine.h @@ -51,13 +51,11 @@ public: void handleRemoteSetupDone(int port); void handleRemoteSetupFailed(const QString &message); - void setAttachToRunningExternalApp(bool value); - void shutdownInferiorAsSlave(); - void shutdownEngineAsSlave(); - void pauseConnection(); void gotoLocation(const QString &fileName, int lineNumber, bool setMarker); void gotoLocation(const Internal::StackFrame &frame, bool setMarker); + void pauseConnection(); + public slots: void messageReceived(const QByteArray &message); void disconnected(); @@ -128,6 +126,10 @@ private: void expandObject(const QByteArray &iname, quint64 objectId); void sendPing(); + void closeConnection(); + void startApplicationLauncher(); + void stopApplicationLauncher(); + bool isShadowBuildProject() const; QString fromShadowBuildFilename(const QString &filename) const; QString mangleFilenamePaths(const QString &filename, -- 2.11.0