diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index 43266a0d29b07c058ce4530aec57513da5464934..8329a891fe32254e0e627da90e96199dad2be68a 100644 --- a/doc/qtcreator.qdoc +++ b/doc/qtcreator.qdoc @@ -9487,6 +9487,13 @@ libraries on devices. Then select the device as the target before you start debugging. + \section1 Mixed C++/QML Debugging + + You can debug both the C++ and QML parts of your application at the same time: + Select the checkboxes for both languages in the \gui{Run Settings}. However, + C++ breakpoints will be ignored until the debugger has attached also to the QML + engine. + \section1 Starting QML Debugging To start the application, choose \gui {Debug > Start Debugging diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 64dd09c5299bbb0e2c61cf99689722183b27b05d..2e338d411008b8e80e286baa433cb27ad39b3e7d 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -4862,7 +4862,8 @@ void GdbEngine::handleInferiorPrepared() } // Initial attempt to set breakpoints. - if (startParameters().startMode != AttachCore) { + if (startParameters().startMode != AttachCore + && !isSlaveEngine()) { showStatusMessage(tr("Setting breakpoints...")); showMessage(tr("Setting breakpoints...")); attemptBreakpointSynchronization(); diff --git a/src/plugins/debugger/qml/qmlcppengine.cpp b/src/plugins/debugger/qml/qmlcppengine.cpp index a05a7fd35f348148ee76ed60d6b1b3a97d4bffb6..f1037509206c158532fdb84ed662e0994e2a2ddf 100644 --- a/src/plugins/debugger/qml/qmlcppengine.cpp +++ b/src/plugins/debugger/qml/qmlcppengine.cpp @@ -287,7 +287,15 @@ void QmlCppEngine::updateAll() void QmlCppEngine::attemptBreakpointSynchronization() { - d->m_cppEngine->attemptBreakpointSynchronization(); + if (d->m_qmlEngine->state() == InferiorRunOk + || d->m_qmlEngine->state() == InferiorRunRequested + || d->m_qmlEngine->state() == InferiorStopOk + || d->m_qmlEngine->state() == InferiorStopRequested) { + // We expect both engines to be set up correctly before hitting + // any breakpoints, therefore ignore any breakpoints that would + // be hit before QDeclarativeEngine is set up. + d->m_cppEngine->attemptBreakpointSynchronization(); + } d->m_qmlEngine->attemptBreakpointSynchronization(); } @@ -549,15 +557,18 @@ void QmlCppEngine::slaveEngineStateChanged case InferiorRunOk: if (state() == EngineRunRequested) { - if (otherEngine->state() == InferiorRunOk) + if (otherEngine->state() == InferiorRunOk) { + attemptBreakpointSynchronization(); notifyEngineRunAndInferiorRunOk(); - else if (otherEngine->state() == InferiorStopOk) - notifyEngineRunAndInferiorStopOk(); - else + } else { EDEBUG("... WAITING FOR OTHER INFERIOR RUN"); + } } else { if (otherEngine->state() == InferiorRunOk) { EDEBUG("PLANNED INFERIOR RUN"); + if (state() == InferiorStopOk) { + notifyInferiorRunRequested(); + } notifyInferiorRunOk(); } else if (otherEngine->state() == InferiorStopOk) { EDEBUG("PLANNED SINGLE INFERIOR RUN"); @@ -595,9 +606,6 @@ void QmlCppEngine::slaveEngineStateChanged } else if (state() == InferiorStopRequested) { EDEBUG("... AN INFERIOR STOPPED EXPECTEDLY"); notifyInferiorStopOk(); - } else if (otherEngine->state() == EngineRunRequested && otherEngine == d->m_qmlEngine) { - EDEBUG("... BREAKPOINT HIT IN C++ BEFORE QML STARTUP"); - QTimer::singleShot(0, this, SLOT(skipCppBreakpoint())); } else if (state() == EngineRunRequested) { EDEBUG("... AN INFERIOR FAILED STARTUP, OTHER STOPPED EXPECTEDLY"); // wait for failure notification from other engine @@ -686,32 +694,6 @@ void QmlCppEngine::showMessage(const QString &msg, int channel, int timeout) con DebuggerEngine::showMessage(msg, channel, timeout); } -void QmlCppEngine::skipCppBreakpoint() -{ - // only used to skip breakpoint in CPP when QML not ready yet - QTC_ASSERT(d->m_cppEngine->state() == InferiorStopOk, return); - QTC_ASSERT(d->m_qmlEngine->state() == EngineRunRequested, return); - - if (!d->m_msg) { - Core::ICore * const core = Core::ICore::instance(); - d->m_msg = new QMessageBox(core->mainWindow()); - } - - if (d->m_msg->isHidden()) { - d->m_msg->setIcon(QMessageBox::Warning); - d->m_msg->setWindowTitle(tr("QML/C++ Debugging")); - d->m_msg->setText(tr("Cannot stop execution before QML engine is started. Skipping breakpoint.\n" - "Suggestions: Move the breakpoint after QmlApplicationViewer instantiation or switch to C++ only debugging.")); - d->m_msg->setStandardButtons(QMessageBox::Ok); - d->m_msg->setDefaultButton(QMessageBox::Ok); - d->m_msg->setModal(false); - d->m_msg->show(); - } - - d->m_cppEngine->continueInferior(); - resetLocation(); -} - DebuggerEngine *QmlCppEngine::cppEngine() const { return d->m_cppEngine; diff --git a/src/plugins/debugger/qml/qmlcppengine.h b/src/plugins/debugger/qml/qmlcppengine.h index 322e4a9d4473c1044bbf38ea9ab6e00e026adf22..2f7202b3980afdb842c83067ccce7f46f50597b6 100644 --- a/src/plugins/debugger/qml/qmlcppengine.h +++ b/src/plugins/debugger/qml/qmlcppengine.h @@ -125,9 +125,6 @@ protected: void notifyEngineRunAndInferiorRunOk(); void notifyInferiorShutdownOk(); -protected slots: - void skipCppBreakpoint(); - private: void engineStateChanged(DebuggerState newState); void setState(DebuggerState newState, bool forced = false);