void QmlCppEngine::setupEngine() { EDEBUG("\nMASTER SETUP ENGINE"); setActiveEngine(m_cppEngine); m_qmlEngine->setupSlaveEngine(); m_cppEngine->setupSlaveEngine(); if (startParameters().remoteSetupNeeded) notifyEngineRequestRemoteSetup(); }
QmlCppEngine::QmlCppEngine(const DebuggerRunParameters &rp, QStringList *errors) : DebuggerEngine(rp) { setObjectName(QLatin1String("QmlCppEngine")); m_qmlEngine = new QmlEngine(rp, this); QStringList innerErrors; m_cppEngine = createEngine(rp.cppEngineType, rp, &innerErrors); if (!m_cppEngine) { errors->append(tr("The slave debugging engine required for combined " "QML/C++-Debugging could not be created: %1") .arg(innerErrors.join(QLatin1Char('\n')))); return; } m_cppEngine->setMasterEngine(this); setActiveEngine(m_cppEngine); }
void QmlCppEngine::slaveEngineStateChanged (DebuggerEngine *slaveEngine, const DebuggerState newState) { DebuggerEngine *otherEngine = (slaveEngine == m_cppEngine) ? m_qmlEngine : m_cppEngine; QTC_CHECK(otherEngine != slaveEngine); if (debug) { EDEBUG("GOT SLAVE STATE: " << slaveEngine << newState); EDEBUG(" OTHER ENGINE: " << otherEngine << otherEngine->state()); EDEBUG(" COMBINED ENGINE: " << this << state() << isDying()); } // Idea is to follow the state of the cpp engine, except where we are stepping in QML. // That is, when the QmlEngine moves between InferiorStopOk, and InferiorRunOk, InferiorStopOk ... // // Accordingly, the 'active engine' is the cpp engine until the qml engine enters the // InferiorStopOk state. The cpp engine becomes the active one again as soon as it itself enters // the InferiorStopOk state. if (slaveEngine == m_cppEngine) { switch (newState) { case DebuggerNotReady: { // Can this ever happen? break; } case EngineSetupRequested: { // set by queueSetupEngine() QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state()); break; } case EngineSetupFailed: { qmlEngine()->quitDebugger(); notifyEngineSetupFailed(); break; } case EngineSetupOk: { notifyEngineSetupOk(); break; } case InferiorSetupRequested: { // set by queueSetupInferior() QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state()); break; } case InferiorSetupFailed: { qmlEngine()->quitDebugger(); notifyInferiorSetupFailed(); break; } case InferiorSetupOk: { notifyInferiorSetupOk(); break; } case EngineRunRequested: { // set by queueRunEngine() break; } case EngineRunFailed: { qmlEngine()->quitDebugger(); notifyEngineRunFailed(); break; } case InferiorUnrunnable: { qmlEngine()->quitDebugger(); notifyInferiorUnrunnable(); break; } case InferiorRunRequested: { // might be set already by notifyInferiorRunRequested() QTC_ASSERT(state() == InferiorRunRequested || state() == InferiorStopOk, qDebug() << state()); if (state() != InferiorRunRequested) notifyInferiorRunRequested(); break; } case InferiorRunOk: { QTC_ASSERT(state() == EngineRunRequested || state() == InferiorRunRequested, qDebug() << state()); if (state() == EngineRunRequested) notifyEngineRunAndInferiorRunOk(); else if (state() == InferiorRunRequested) notifyInferiorRunOk(); if (qmlEngine()->state() == InferiorStopOk) { // track qml engine again setState(InferiorStopRequested); notifyInferiorStopOk(); setActiveEngine(m_qmlEngine); } break; } case InferiorRunFailed: { qmlEngine()->quitDebugger(); notifyInferiorRunFailed(); break; } case InferiorStopRequested: { if (m_activeEngine == cppEngine()) { // might be set by doInterruptInferior() QTC_ASSERT(state() == InferiorStopRequested || state() == InferiorRunOk, qDebug() << state()); if (state() == InferiorRunOk) setState(InferiorStopRequested); } else { // we're debugging qml, but got an interrupt, or abort QTC_ASSERT(state() == InferiorRunOk || state() == InferiorStopOk || state() == InferiorRunRequested, qDebug() << state()); if (state() == InferiorRunOk) { setState(InferiorStopRequested); } else if (state() == InferiorStopOk) { notifyInferiorRunRequested(); notifyInferiorRunOk(); setState(InferiorStopRequested); } else if (state() == InferiorRunRequested) { notifyInferiorRunOk(); setState(InferiorStopRequested); } // now track cpp engine setActiveEngine(m_cppEngine); } break; } case InferiorStopOk: { if (isDying()) { EDEBUG("... CPP ENGINE STOPPED DURING SHUTDOWN "); QTC_ASSERT(state() == InferiorStopRequested || state() == InferiorRunOk || state() == InferiorStopOk, qDebug() << state()); // Just to make sure, we're shutting down anyway ... setActiveEngine(m_cppEngine); if (state() == InferiorStopRequested) setState(InferiorStopOk); // otherwise we're probably inside notifyInferiorStopOk already } else { if (m_activeEngine != cppEngine()) { showStatusMessage(tr("C++ debugger activated")); setActiveEngine(m_cppEngine); } QTC_ASSERT(state() == InferiorStopRequested || state() == InferiorRunRequested || state() == EngineRunRequested || state() == InferiorRunOk || state() == InferiorStopOk, qDebug() << state()); switch (state()) { case InferiorStopRequested: EDEBUG("... CPP ENGINE STOPPED EXPECTEDLY"); notifyInferiorStopOk(); break; case EngineRunRequested: EDEBUG("... CPP ENGINE STOPPED ON STARTUP"); notifyEngineRunAndInferiorStopOk(); break; case InferiorRunOk: EDEBUG("... CPP ENGINE STOPPED SPONTANEOUSLY"); notifyInferiorSpontaneousStop(); break; case InferiorRunRequested: // can happen if qml engine was active notifyInferiorRunFailed(); default: break; } } break; } case InferiorStopFailed: { QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state()); notifyInferiorStopFailed(); break; } case InferiorExitOk: { // InferiorExitOk will be called through notifyInferiorExited // when InferiorShutDownOk is reached qmlEngine()->quitDebugger(); break; } case InferiorShutdownRequested: { // might be set by queueShutdownInferior() already QTC_ASSERT(state() == InferiorShutdownRequested || state() == InferiorStopOk, qDebug() << state()); if (state() == InferiorStopOk) setState(InferiorShutdownRequested); qmlEngine()->quitDebugger(); break; } case InferiorShutdownFailed: { QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state()); notifyInferiorShutdownFailed(); break; } case InferiorShutdownOk: { if (state() == InferiorShutdownRequested) { notifyInferiorShutdownOk(); } else { // we got InferiorExitOk before, but ignored it ... notifyInferiorExited(); } break; } case EngineShutdownRequested: { // set by queueShutdownEngine() QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state()); break; } case EngineShutdownFailed: { QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state()); notifyEngineShutdownFailed(); break; } case EngineShutdownOk: { QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state()); notifyEngineShutdownOk(); break; } case DebuggerFinished: { // set by queueFinishDebugger() QTC_ASSERT(state() == DebuggerFinished, qDebug() << state()); break; } } } else { // QML engine state change if (newState == InferiorStopOk) { if (isDying()) { EDEBUG("... QML ENGINE STOPPED DURING SHUTDOWN "); // Just to make sure, we're shutting down anyway ... setActiveEngine(m_cppEngine); if (state() == InferiorStopRequested) notifyInferiorStopOk(); // otherwise we're probably inside notifyInferiorStopOk already } else { if (m_activeEngine != qmlEngine()) { showStatusMessage(tr("QML debugger activated")); setActiveEngine(m_qmlEngine); } QTC_ASSERT(state() == InferiorRunOk || state() == InferiorStopRequested || state() == InferiorShutdownRequested, qDebug() << state()); if (state() == InferiorRunOk) notifyInferiorSpontaneousStop(); else if (state() == InferiorStopRequested) notifyInferiorStopOk(); } } else if (newState == InferiorRunOk) { if (m_activeEngine == qmlEngine()) { QTC_ASSERT(state() == InferiorRunRequested, qDebug() << state()); notifyInferiorRunOk(); } } } }