OSDN Git Service

QmlCpp Debugging: Only set C++ breakpoints after QML is connected
authorKai Koehne <kai.koehne@nokia.com>
Wed, 3 Aug 2011 12:48:56 +0000 (14:48 +0200)
committerKai Koehne <kai.koehne@nokia.com>
Thu, 4 Aug 2011 08:54:59 +0000 (10:54 +0200)
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
src/plugins/debugger/gdb/gdbengine.cpp
src/plugins/debugger/qml/qmlcppengine.cpp
src/plugins/debugger/qml/qmlcppengine.h

index 43266a0..8329a89 100644 (file)
     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
index 64dd09c..2e338d4 100644 (file)
@@ -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();
index a05a7fd..f103750 100644 (file)
@@ -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;
index 322e4a9..2f7202b 100644 (file)
@@ -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);