From 7c31bd660454bcf473012ac1f86f4bb4d4b038e7 Mon Sep 17 00:00:00 2001 From: Kai Koehne <kai.koehne@nokia.com> Date: Wed, 3 Aug 2011 14:48:56 +0200 Subject: [PATCH] QmlCpp Debugging: Only set C++ breakpoints after QML is connected If one hits a C++ breakpoint before the QmlEngine is properly set up the debugging actions are all disabled. Patch 58faedc4e tried to fix this by automatically executing continue in these cases, but this let to errors on Mac OS X. Instead just delay the setting of C++ breakpoints. Task-number: QTCREATORBUG-5681 Change-Id: I149dea9b453ed7abd33a1a93b5b546d7c6cda8fd Reviewed-on: http://codereview.qt.nokia.com/2568 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Christiaan Janssen <christiaan.janssen@nokia.com> --- doc/qtcreator.qdoc | 7 ++++ src/plugins/debugger/gdb/gdbengine.cpp | 3 +- src/plugins/debugger/qml/qmlcppengine.cpp | 50 ++++++++--------------- src/plugins/debugger/qml/qmlcppengine.h | 3 -- 4 files changed, 25 insertions(+), 38 deletions(-) diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index 43266a0d29b..8329a891fe3 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 64dd09c5299..2e338d41100 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 a05a7fd35f3..f1037509206 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 322e4a9d447..2f7202b3980 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); -- GitLab