OSDN Git Service

Merge remote branch 'origin/2.1'
[qt-creator-jp/qt-creator-jp.git] / src / plugins / debugger / debuggerengine.cpp
index bed156e..cbb287f 100644 (file)
 #include "debuggeractions.h"
 #include "debuggeragents.h"
 #include "debuggerrunner.h"
-#include "debuggeroutputwindow.h"
 #include "debuggerplugin.h"
 #include "debuggerstringutils.h"
+#include "debuggertooltip.h"
+#include "logwindow.h"
 
 #include "breakhandler.h"
 #include "moduleshandler.h"
 
 #include <coreplugin/icore.h>
 #include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/progressmanager/progressmanager.h>
+#include <coreplugin/progressmanager/futureprogress.h>
 
 #include <projectexplorer/debugginghelper.h>
-#include <projectexplorer/environment.h>
-#include <projectexplorer/project.h>
-#include <projectexplorer/projectexplorerconstants.h>
-#include <projectexplorer/target.h>
-#include <projectexplorer/buildconfiguration.h>
-#include <projectexplorer/applicationrunconfiguration.h> // For LocalApplication*
+#include <projectexplorer/toolchain.h>
 
 #include <qt4projectmanager/qt4projectmanagerconstants.h>
 
 #include <texteditor/itexteditor.h>
 
+#include <utils/environment.h>
 #include <utils/savedaction.h>
 #include <utils/qtcassert.h>
 
@@ -68,6 +67,7 @@
 #include <QtCore/QDir>
 #include <QtCore/QFileInfo>
 #include <QtCore/QTimer>
+#include <QtCore/QFutureInterface>
 
 #include <QtGui/QAbstractItemView>
 #include <QtGui/QStandardItemModel>
@@ -102,12 +102,18 @@ using namespace TextEditor;
 //
 ///////////////////////////////////////////////////////////////////////
 
-DebuggerStartParameters::DebuggerStartParameters()
-  : attachPID(-1),
+DebuggerStartParameters::DebuggerStartParameters() :
+    isSnapshot(false),
+    attachPID(-1),
     useTerminal(false),
     breakAtMain(false),
+    qmlServerAddress("127.0.0.1"),
+    qmlServerPort(0),
+    useServerStartScript(false),
+    connParams(SshConnectionParameters::NoProxy),
     toolChainType(ToolChain::UNKNOWN),
-    startMode(NoStartMode)
+    startMode(NoStartMode),
+    executableUid(0)
 {}
 
 void DebuggerStartParameters::clear()
@@ -138,14 +144,12 @@ QDebug operator<<(QDebug str, const DebuggerStartParameters &sp)
             << " remoteChannel=" << sp.remoteChannel
             << " remoteArchitecture=" << sp.remoteArchitecture
             << " symbolFileName=" << sp.symbolFileName
+            << " useServerStartScript=" << sp.useServerStartScript
             << " serverStartScript=" << sp.serverStartScript
             << " toolchain=" << sp.toolChainType << '\n';
     return str;
 }
 
-
-namespace Internal {
-
 const char *DebuggerEngine::stateName(int s)
 {
 #    define SN(x) case x: return #x;
@@ -229,9 +233,12 @@ public:
         m_stackHandler(engine),
         m_threadsHandler(engine),
         m_watchHandler(engine),
-        m_disassemblerViewAgent(engine)
+        m_disassemblerViewAgent(engine),
+        m_runInWrapperEngine(false)
     {}
 
+    ~DebuggerEnginePrivate() {}
+
 public slots:
     void breakpointSetRemoveMarginActionTriggered();
     void breakpointEnableDisableMarginActionTriggered();
@@ -263,12 +270,15 @@ public slots:
     }
 
     void queueFinishDebugger() {
-        m_engine->setState(DebuggerFinished, true);
-        m_engine->showMessage(_("QUEUE: SHUTDOWN INFERIOR"));
+        QTC_ASSERT(state() == EngineShutdownOk
+            || state() == EngineShutdownFailed, qDebug() << state());
+        m_engine->setState(DebuggerFinished);
+        m_engine->showMessage(_("QUEUE: FINISH DEBUGGER"));
         QTimer::singleShot(0, this, SLOT(doFinishDebugger()));
     }
 
     void raiseApplication() {
+        QTC_ASSERT(m_runControl, return);
         m_runControl->bringApplicationToForeground(m_inferiorPid);
     }
 
@@ -302,6 +312,9 @@ public:
     ThreadsHandler m_threadsHandler;
     WatchHandler m_watchHandler;
     DisassemblerViewAgent m_disassemblerViewAgent;
+    QFutureInterface<void> m_progress;
+
+    bool m_runInWrapperEngine;
 };
 
 void DebuggerEnginePrivate::breakpointSetRemoveMarginActionTriggered()
@@ -309,10 +322,11 @@ void DebuggerEnginePrivate::breakpointSetRemoveMarginActionTriggered()
     QAction *act = qobject_cast<QAction *>(sender());
     QTC_ASSERT(act, return);
     QList<QVariant> list = act->data().toList();
-    QTC_ASSERT(list.size() == 2, return);
+    QTC_ASSERT(list.size() >= 3, qDebug() << list; return);
     const QString fileName = list.at(0).toString();
     const int lineNumber = list.at(1).toInt();
-    m_breakHandler.toggleBreakpoint(fileName, lineNumber);
+    const quint64 address = list.at(2).toULongLong();
+    m_breakHandler.toggleBreakpoint(fileName, lineNumber, address);
 }
 
 void DebuggerEnginePrivate::breakpointEnableDisableMarginActionTriggered()
@@ -320,7 +334,7 @@ void DebuggerEnginePrivate::breakpointEnableDisableMarginActionTriggered()
     QAction *act = qobject_cast<QAction *>(sender());
     QTC_ASSERT(act, return);
     QList<QVariant> list = act->data().toList();
-    QTC_ASSERT(list.size() == 2, return);
+    QTC_ASSERT(list.size() == 3, qDebug() << list; return);
     const QString fileName = list.at(0).toString();
     const int lineNumber = list.at(1).toInt();
     m_breakHandler.toggleBreakpointEnabled(fileName, lineNumber);
@@ -329,37 +343,37 @@ void DebuggerEnginePrivate::breakpointEnableDisableMarginActionTriggered()
 void DebuggerEnginePrivate::handleContextMenuRequest(const QVariant &parameters)
 {
     const QList<QVariant> list = parameters.toList();
-    QTC_ASSERT(list.size() == 3, return);
+    QTC_ASSERT(list.size() == 3, qDebug() << list; return);
     TextEditor::ITextEditor *editor =
         (TextEditor::ITextEditor *)(list.at(0).value<quint64>());
     int lineNumber = list.at(1).toInt();
     QMenu *menu = (QMenu *)(list.at(2).value<quint64>());
 
     BreakpointData *data = 0;
-    QString position;
     QString fileName;
+    quint64 address = 0;
     if (editor->property("DisassemblerView").toBool()) {
         fileName = editor->file()->fileName();
         QString line = editor->contents()
             .section('\n', lineNumber - 1, lineNumber - 1);
-        position = _("*") + fileName;
         BreakpointData needle;
-        needle.bpAddress = line.left(line.indexOf(QLatin1Char(' '))).toLatin1();
-        needle.bpLineNumber = "-1";
+        address = needle.address = DisassemblerViewAgent::addressFromDisassemblyLine(line);
+        needle.bpLineNumber = -1;
         data = m_breakHandler.findSimilarBreakpoint(&needle);
     } else {
         fileName = editor->file()->fileName();
-        position = fileName + QString(":%1").arg(lineNumber);
         data = m_breakHandler.findBreakpoint(fileName, lineNumber);
     }
 
     QList<QVariant> args;
     args.append(fileName);
     args.append(lineNumber);
+    args.append(address);
 
     if (data) {
         // existing breakpoint
-        QAction *act = new QAction(tr("Remove Breakpoint"), menu);
+        const QString number = QString::fromAscii(data->bpNumber);
+        QAction *act = new QAction(tr("Remove Breakpoint %1").arg(number), menu);
         act->setData(args);
         connect(act, SIGNAL(triggered()),
             this, SLOT(breakpointSetRemoveMarginActionTriggered()));
@@ -367,16 +381,19 @@ void DebuggerEnginePrivate::handleContextMenuRequest(const QVariant &parameters)
 
         QAction *act2;
         if (data->enabled)
-            act2 = new QAction(tr("Disable Breakpoint"), menu);
+            act2 = new QAction(tr("Disable Breakpoint %1").arg(number), menu);
         else
-            act2 = new QAction(tr("Enable Breakpoint"), menu);
+            act2 = new QAction(tr("Enable Breakpoint %1").arg(number), menu);
         act2->setData(args);
         connect(act2, SIGNAL(triggered()),
             this, SLOT(breakpointEnableDisableMarginActionTriggered()));
         menu->addAction(act2);
     } else {
         // non-existing
-        QAction *act = new QAction(tr("Set Breakpoint"), menu);
+        const QString text = address ?
+                    tr("Set Breakpoint at 0x%1").arg(address, 0, 16) :
+                    tr("Set Breakpoint at line %1").arg(lineNumber);
+        QAction *act = new QAction(text, menu);
         act->setData(args);
         connect(act, SIGNAL(triggered()),
             this, SLOT(breakpointSetRemoveMarginActionTriggered()));
@@ -406,11 +423,26 @@ void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
     showMessage(msg, StatusBar, timeout);
 }
 
+void DebuggerEngine::removeTooltip()
+{
+    watchHandler()->removeTooltip();
+    hideDebuggerToolTip();
+}
+
 void DebuggerEngine::handleCommand(int role, const QVariant &value)
 {
-    //qDebug() << "COMMAND: " << role << value;
+    if (role != RequestToolTipByExpressionRole)
+        removeTooltip();
 
     switch (role) {
+        case RequestActivateFrameRole:
+            activateFrame(value.toInt());
+            break;
+
+        case RequestReloadFullStackRole:
+            reloadFullStack();
+            break;
+
         case RequestReloadSourceFilesRole:
             reloadSourceFiles();
             break;
@@ -475,8 +507,8 @@ void DebuggerEngine::handleCommand(int role, const QVariant &value)
             d->queueShutdownInferior();
             break;
 
-        case RequestMakeSnapshotRole:
-            makeSnapshot();
+        case RequestCreateSnapshotRole:
+            createSnapshot();
             break;
 
         case RequestActivationRole:
@@ -525,6 +557,12 @@ void DebuggerEngine::handleCommand(int role, const QVariant &value)
             d->handleContextMenuRequest(list);
             break;
         }
+
+        case RequestShowMemoryRole: {
+            qDebug() << "CREATING MEMORY VIEW";
+            (void) MemoryViewAgent(this, "0x0");
+            break;
+        }
     }
 }
 
@@ -602,52 +640,82 @@ SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
 
 QAbstractItemModel *DebuggerEngine::modulesModel() const
 {
-    return d->m_modulesHandler.model();
+    QAbstractItemModel *model = d->m_modulesHandler.model();
+    if (model->objectName().isEmpty()) // Make debugging easier.
+        model->setObjectName(objectName() + QLatin1String("ModulesModel"));
+    return model;
 }
 
 QAbstractItemModel *DebuggerEngine::breakModel() const
 {
-    return d->m_breakHandler.model();
+    QAbstractItemModel *model = d->m_breakHandler.model();
+    if (model->objectName().isEmpty()) // Make debugging easier.
+        model->setObjectName(objectName() + QLatin1String("BreakModel"));
+    return model;
 }
 
 QAbstractItemModel *DebuggerEngine::registerModel() const
 {
-    return d->m_registerHandler.model();
+    QAbstractItemModel *model = d->m_registerHandler.model();
+    if (model->objectName().isEmpty()) // Make debugging easier.
+        model->setObjectName(objectName() + QLatin1String("RegisterModel"));
+    return model;
 }
 
 QAbstractItemModel *DebuggerEngine::stackModel() const
 {
-    return d->m_stackHandler.model();
+    QAbstractItemModel *model = d->m_stackHandler.model();
+    if (model->objectName().isEmpty()) // Make debugging easier.
+        model->setObjectName(objectName() + QLatin1String("StackModel"));
+    return model;
 }
 
 QAbstractItemModel *DebuggerEngine::threadsModel() const
 {
-    return d->m_threadsHandler.model();
+    QAbstractItemModel *model = d->m_threadsHandler.model();
+    if (model->objectName().isEmpty()) // Make debugging easier.
+        model->setObjectName(objectName() + QLatin1String("ThreadsModel"));
+    return model;
 }
 
 QAbstractItemModel *DebuggerEngine::localsModel() const
 {
-    return d->m_watchHandler.model(LocalsWatch);
+    QAbstractItemModel *model = d->m_watchHandler.model(LocalsWatch);
+    if (model->objectName().isEmpty()) // Make debugging easier.
+        model->setObjectName(objectName() + QLatin1String("LocalsModel"));
+    return model;
 }
 
 QAbstractItemModel *DebuggerEngine::watchersModel() const
 {
-    return d->m_watchHandler.model(WatchersWatch);
+    QAbstractItemModel *model = d->m_watchHandler.model(WatchersWatch);
+    if (model->objectName().isEmpty()) // Make debugging easier.
+        model->setObjectName(objectName() + QLatin1String("WatchersModel"));
+    return model;
 }
 
 QAbstractItemModel *DebuggerEngine::returnModel() const
 {
-    return d->m_watchHandler.model(ReturnWatch);
+    QAbstractItemModel *model = d->m_watchHandler.model(ReturnWatch);
+    if (model->objectName().isEmpty()) // Make debugging easier.
+        model->setObjectName(objectName() + QLatin1String("ReturnModel"));
+    return model;
 }
 
 QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
 {
-    return d->m_sourceFilesHandler.model();
+    QAbstractItemModel *model = d->m_sourceFilesHandler.model();
+    if (model->objectName().isEmpty()) // Make debugging easier.
+        model->setObjectName(objectName() + QLatin1String("SourceFilesModel"));
+    return model;
 }
 
 QAbstractItemModel *DebuggerEngine::commandModel() const
 {
-    return d->m_commandHandler.model();
+    QAbstractItemModel *model = d->m_commandHandler.model();
+    if (model->objectName().isEmpty()) // Make debugging easier.
+        model->setObjectName(objectName() + QLatin1String("CommandModel"));
+    return model;
 }
 
 void DebuggerEngine::fetchMemory(MemoryViewAgent *, QObject *,
@@ -667,12 +735,24 @@ void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) c
 {
     //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
     //    qDebug() << qPrintable(msg) << "IN STATE" << state();
-    d->m_runControl->showMessage(msg, channel);
     plugin()->showMessage(msg, channel, timeout);
+    if (d->m_runControl) {
+        d->m_runControl->showMessage(msg, channel);
+    } else {
+        qWarning("Warning: %s (no active run control)", qPrintable(msg));
+    }
 }
 
 void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
 {
+    if (!isSessionEngine() && !d->m_runInWrapperEngine) {
+        d->m_progress.setProgressRange(0, 1000);
+        Core::FutureProgress *fp = Core::ICore::instance()->progressManager()
+            ->addTask(d->m_progress.future(),
+            tr("Launching"), _("Debugger.Launcher"));
+        fp->setKeepOnFinish(false);
+        d->m_progress.reportStarted();
+    }
     QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
     QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
 
@@ -685,13 +765,11 @@ void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
 
     d->m_runControl = runControl;
 
-    QTC_ASSERT(state() == DebuggerNotReady, qDebug() << state());
-
     d->m_inferiorPid = d->m_startParameters.attachPID > 0
         ? d->m_startParameters.attachPID : 0;
 
     if (d->m_startParameters.environment.empty())
-        d->m_startParameters.environment = Environment().toStringList();
+        d->m_startParameters.environment = Utils::Environment().toStringList();
 
     if (d->m_startParameters.breakAtMain)
         breakByFunctionMain();
@@ -700,7 +778,11 @@ void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
     theDebuggerAction(OperateByInstruction)
         ->setEnabled(engineCapabilities & DisassemblerCapability);
 
+    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
+         qDebug() << state());
     setState(EngineSetupRequested);
+
+    d->m_progress.setProgressValue(200);
     setupEngine();
 }
 
@@ -870,8 +952,21 @@ void DebuggerEngine::addToWatchWindow()
 }
 
 // Called from RunControl.
+void DebuggerEngine::handleStartFailed()
+{
+    showMessage("HANDLE RUNCONTROL START FAILED");
+    d->m_runControl = 0;
+
+    d->m_progress.setProgressValue(900);
+    d->m_progress.reportCanceled();
+    d->m_progress.reportFinished();
+}
+
+// Called from RunControl.
 void DebuggerEngine::handleFinished()
 {
+    showMessage("HANDLE RUNCONTROL FINISHED");
+    d->m_runControl = 0;
     modulesHandler()->removeAll();
     stackHandler()->removeAll();
     threadsHandler()->removeAll();
@@ -881,6 +976,9 @@ void DebuggerEngine::handleFinished()
     QTC_ASSERT(sessionTemplate != this, /**/);
     breakHandler()->storeToTemplate(sessionTemplate->breakHandler());
     watchHandler()->storeToTemplate(sessionTemplate->watchHandler());
+
+    d->m_progress.setProgressValue(1000);
+    d->m_progress.reportFinished();
 }
 
 const DebuggerStartParameters &DebuggerEngine::startParameters() const
@@ -922,23 +1020,22 @@ QStringList DebuggerEngine::qtDumperLibraryLocations() const
 
 void DebuggerEngine::showQtDumperLibraryWarning(const QString &details)
 {
-    //QMessageBox dialog(d->m_mainWindow); // FIXME
-    QMessageBox dialog;
-    QPushButton *qtPref = dialog.addButton(tr("Open Qt preferences"),
+    QMessageBox dialog(plugin()->mainWindow());
+    QPushButton *qtPref = dialog.addButton(tr("Open Qt4 Options"),
         QMessageBox::ActionRole);
-    QPushButton *helperOff = dialog.addButton(tr("Turn off helper usage"),
+    QPushButton *helperOff = dialog.addButton(tr("Turn off Helper Usage"),
         QMessageBox::ActionRole);
-    QPushButton *justContinue = dialog.addButton(tr("Continue anyway"),
+    QPushButton *justContinue = dialog.addButton(tr("Continue Anyway"),
         QMessageBox::AcceptRole);
     dialog.setDefaultButton(justContinue);
-    dialog.setWindowTitle(tr("Debugging helper missing"));
+    dialog.setWindowTitle(tr("Debugging Helper Missing"));
     dialog.setText(tr("The debugger could not load the debugging helper library."));
     dialog.setInformativeText(tr(
         "The debugging helper is used to nicely format the values of some Qt "
         "and Standard Library data types. "
         "It must be compiled for each used Qt version separately. "
-        "This can be done in the Qt preferences page by selecting a Qt installation "
-        "and clicking on 'Rebuild' in the 'Debugging Helper' row."));
+        "On the Qt4 options page, select a Qt installation "
+        "and click Rebuild."));
     if (!details.isEmpty())
         dialog.setDetailedText(details);
     dialog.exec();
@@ -952,6 +1049,35 @@ void DebuggerEngine::showQtDumperLibraryWarning(const QString &details)
     }
 }
 
+void DebuggerEngine::showQmlObserverToolWarning()
+{
+    QMessageBox dialog(plugin()->mainWindow());
+    QPushButton *qtPref = dialog.addButton(tr("Open Qt4 Options"),
+        QMessageBox::ActionRole);
+    QPushButton *helperOff = dialog.addButton(tr("Turn off QML Observer Usage"),
+        QMessageBox::ActionRole);
+    QPushButton *justContinue = dialog.addButton(tr("Continue Anyway"),
+        QMessageBox::AcceptRole);
+    dialog.setDefaultButton(justContinue);
+    dialog.setWindowTitle(tr("QML Observer Missing"));
+    dialog.setText(tr("QML Observer could not be found."));
+    dialog.setInformativeText(tr(
+        "QML Observer is used to offer additional debugging features for "
+        "QML applications, such as interactive debugging and inspection tools."
+        "It must be compiled for each used Qt version separately. "
+        "On the Qt4 options page, select a Qt installation "
+        "and click Rebuild."));
+    dialog.exec();
+    if (dialog.clickedButton() == qtPref) {
+        Core::ICore::instance()->showOptionsDialog(
+            _(Qt4ProjectManager::Constants::QT_SETTINGS_CATEGORY),
+            _(Qt4ProjectManager::Constants::QTVERSION_SETTINGS_PAGE_ID));
+    } else if (dialog.clickedButton() == helperOff) {
+        theDebuggerAction(UseQmlObserver)
+            ->setValue(qVariantFromValue(false), false);
+    }
+}
+
 QString DebuggerEngine::qtDumperLibraryName() const
 {
     if (theDebuggerAction(UseCustomDebuggingHelperLocation)->value().toBool())
@@ -983,7 +1109,7 @@ static bool isAllowedTransition(DebuggerState from, DebuggerState to)
     case EngineSetupRequested:
         return to == EngineSetupOk || to == EngineSetupFailed;
     case EngineSetupFailed:
-        // FIXME: In therory it's the engine's task to go into a 
+        // FIXME: In therory it's the engine's task to go into a
         // proper "Shutdown" state before calling notifyEngineSetupFailed
         //return to == DebuggerFinished;
         return to == EngineShutdownRequested;
@@ -1027,14 +1153,14 @@ static bool isAllowedTransition(DebuggerState from, DebuggerState to)
         return to == EngineShutdownRequested;
 
     case EngineShutdownRequested:
-        return to == EngineShutdownOk;
+        return to == EngineShutdownOk || to == EngineShutdownFailed;
     case EngineShutdownOk:
         return to == DebuggerFinished;
     case EngineShutdownFailed:
         return to == DebuggerFinished;
 
     case DebuggerFinished:
-        return false;
+        return to == EngineSetupRequested; // Happens on restart.
     }
 
     qDebug() << "UNKNOWN STATE:" << from;
@@ -1046,6 +1172,7 @@ void DebuggerEngine::notifyEngineSetupFailed()
     showMessage(_("NOTE: ENGINE SETUP FAILED"));
     QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
     setState(EngineSetupFailed);
+    QTC_ASSERT(d->m_runControl, return);
     d->m_runControl->startFailed();
     d->queueShutdownEngine();
 }
@@ -1055,16 +1182,17 @@ void DebuggerEngine::notifyEngineSetupOk()
     showMessage(_("NOTE: ENGINE SETUP OK"));
     QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
     setState(EngineSetupOk);
-    d->m_runControl->startSuccessful();
+    QTC_ASSERT(d->m_runControl, return);
     showMessage(_("QUEUE: SETUP INFERIOR"));
     QTimer::singleShot(0, d, SLOT(doSetupInferior()));
 }
 
 void DebuggerEnginePrivate::doSetupInferior()
 {
+    m_engine->showMessage(_("CALL: SETUP INFERIOR"));
     QTC_ASSERT(state() == EngineSetupOk, qDebug() << state());
+    m_progress.setProgressValue(250);
     m_engine->setState(InferiorSetupRequested);
-    m_engine->showMessage(_("CALL: SETUP INFERIOR"));
     m_engine->setupInferior();
 }
 
@@ -1087,12 +1215,15 @@ void DebuggerEnginePrivate::doRunEngine()
 {
     m_engine->showMessage(_("CALL: RUN ENGINE"));
     QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
+    m_progress.setProgressValue(300);
     m_engine->runEngine();
 }
 
 void DebuggerEngine::notifyInferiorUnrunnable()
 {
     showMessage(_("NOTE: INFERIOR UNRUNNABLE"));
+    d->m_progress.setProgressValue(1000);
+    d->m_progress.reportFinished();
     QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
     setState(InferiorUnrunnable);
 }
@@ -1101,6 +1232,9 @@ void DebuggerEngine::notifyEngineRunFailed()
 {
     showMessage(_("NOTE: ENGINE RUN FAILED"));
     QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
+    d->m_progress.setProgressValue(900);
+    d->m_progress.reportCanceled();
+    d->m_progress.reportFinished();
     setState(EngineRunFailed);
     d->queueShutdownInferior();
 }
@@ -1108,6 +1242,8 @@ void DebuggerEngine::notifyEngineRunFailed()
 void DebuggerEngine::notifyEngineRunAndInferiorRunOk()
 {
     showMessage(_("NOTE: ENGINE RUN AND INFERIOR RUN OK"));
+    d->m_progress.setProgressValue(1000);
+    d->m_progress.reportFinished();
     QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
     setState(InferiorRunRequested);
     notifyInferiorRunOk();
@@ -1116,6 +1252,8 @@ void DebuggerEngine::notifyEngineRunAndInferiorRunOk()
 void DebuggerEngine::notifyEngineRunAndInferiorStopOk()
 {
     showMessage(_("NOTE: ENGINE RUN AND INFERIOR STOP OK"));
+    d->m_progress.setProgressValue(1000);
+    d->m_progress.reportFinished();
     QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
     setState(InferiorStopRequested);
     notifyInferiorStopOk();
@@ -1193,6 +1331,7 @@ void DebuggerEnginePrivate::doInterruptInferior()
 
 void DebuggerEnginePrivate::doShutdownInferior()
 {
+    QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state());
     m_engine->resetLocation();
     m_targetState = DebuggerFinished;
     m_engine->showMessage(_("CALL: SHUTDOWN INFERIOR"));
@@ -1235,8 +1374,7 @@ void DebuggerEngine::notifyInferiorIll()
 
 void DebuggerEnginePrivate::doShutdownEngine()
 {
-    QTC_ASSERT(state() == EngineShutdownRequested
-           || state() == InferiorShutdownOk, qDebug() << state());
+    QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
     m_targetState = DebuggerFinished;
     m_engine->showMessage(_("CALL: SHUTDOWN ENGINE"));
     m_engine->shutdownEngine();
@@ -1247,7 +1385,11 @@ void DebuggerEngine::notifyEngineShutdownOk()
     showMessage(_("NOTE: ENGINE SHUTDOWN OK"));
     QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
     setState(EngineShutdownOk);
-    QTimer::singleShot(0, d, SLOT(doFinishDebugger()));
+    if (!d->m_runInWrapperEngine) {
+        d->queueFinishDebugger();
+    } else {
+        setState(DebuggerFinished);
+    }
 }
 
 void DebuggerEngine::notifyEngineShutdownFailed()
@@ -1255,16 +1397,19 @@ void DebuggerEngine::notifyEngineShutdownFailed()
     showMessage(_("NOTE: ENGINE SHUTDOWN FAILED"));
     QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
     setState(EngineShutdownFailed);
-    QTimer::singleShot(0, d, SLOT(doFinishDebugger()));
+    if (!d->m_runInWrapperEngine) {
+        d->queueFinishDebugger();
+    } else {
+        setState(DebuggerFinished);
+    }
 }
 
 void DebuggerEnginePrivate::doFinishDebugger()
 {
     m_engine->showMessage(_("NOTE: FINISH DEBUGGER"));
-    QTC_ASSERT(state() == EngineShutdownOk
-        || state() == EngineShutdownFailed, qDebug() << state());
+    QTC_ASSERT(state() == DebuggerFinished, qDebug() << state());
     m_engine->resetLocation();
-    m_engine->setState(DebuggerFinished);
+    QTC_ASSERT(m_runControl, return);
     m_runControl->debuggingFinished();
 }
 
@@ -1290,6 +1435,7 @@ void DebuggerEngine::notifyEngineIll()
 void DebuggerEngine::notifyEngineSpontaneousShutdown()
 {
     showMessage(_("NOTE: ENGINE SPONTANEOUS SHUTDOWN"));
+    setState(EngineShutdownOk, true);
     d->queueFinishDebugger();
 }
 
@@ -1313,7 +1459,7 @@ void DebuggerEngine::notifyInferiorExited()
 void DebuggerEngine::setState(DebuggerState state, bool forced)
 {
     //qDebug() << "STATUS CHANGE: FROM " << stateName(d->m_state)
-    //        << " TO " << stateName(state);
+    //         << " TO " << stateName(state);
 
     DebuggerState oldState = d->m_state;
     d->m_state = state;
@@ -1324,8 +1470,19 @@ void DebuggerEngine::setState(DebuggerState state, bool forced)
     if (!forced && !isAllowedTransition(oldState, state))
         qDebug() << "UNEXPECTED STATE TRANSITION: " << msg;
 
+    const bool running = d->m_state == InferiorRunOk;
+    if (running)
+        threadsHandler()->notifyRunning();
+
     showMessage(msg, LogDebug);
     plugin()->updateState(this);
+
+    emit stateChanged(d->m_state);
+}
+
+void DebuggerEngine::setRunInWrapperEngine(bool value)
+{
+    d->m_runInWrapperEngine = value;
 }
 
 bool DebuggerEngine::debuggerActionsEnabled() const
@@ -1378,7 +1535,7 @@ qint64 DebuggerEngine::inferiorPid() const
     return d->m_inferiorPid;
 }
 
-DebuggerPlugin *DebuggerEngine::plugin() const
+DebuggerPlugin *DebuggerEngine::plugin()
 {
     return DebuggerPlugin::instance();
 }
@@ -1410,13 +1567,18 @@ void DebuggerEngine::quitDebugger()
 {
     showMessage("QUIT DEBUGGER REQUESTED");
     d->m_targetState = DebuggerFinished;
-    if (state() == InferiorStopOk) {
-        d->doShutdownInferior();
-    } else if (state() == InferiorRunOk) {
+    switch (state()) {
+    case InferiorStopOk:
+    case InferiorStopFailed:
+        d->queueShutdownInferior();
+        break;
+    case InferiorRunOk:
         d->doInterruptInferior();
-    } else {
+        break;
+    default:
         // FIXME: We should disable the actions connected to that
         notifyInferiorIll();
+        break;
     }
 }
 
@@ -1425,7 +1587,182 @@ void DebuggerEngine::requestInterruptInferior()
     d->doInterruptInferior();
 }
 
-} // namespace Internal
+void DebuggerEngine::progressPing()
+{
+    int progress = qMin(d->m_progress.progressValue() + 2, 800);
+    d->m_progress.setProgressValue(progress);
+}
+
+QMessageBox *DebuggerEngine::showMessageBox(int icon, const QString &title,
+    const QString &text, int buttons)
+{
+    return plugin()->showMessageBox(icon, title, text, buttons);
+}
+
+DebuggerRunControl *DebuggerEngine::runControl() const
+{
+    return d->m_runControl;
+}
+
+void DebuggerEngine::setToolTipExpression(const QPoint &, TextEditor::ITextEditor *, int)
+{
+}
+
+void DebuggerEngine::updateWatchData(const Internal::WatchData &, const Internal::WatchUpdateFlags &)
+{
+}
+
+bool DebuggerEngine::isSessionEngine() const
+{
+    return false;
+}
+
+void DebuggerEngine::watchPoint(const QPoint &)
+{
+}
+
+void DebuggerEngine::fetchDisassembler(Internal::DisassemblerViewAgent *)
+{
+}
+
+void DebuggerEngine::activateFrame(int)
+{
+}
+
+void DebuggerEngine::reloadModules()
+{
+}
+
+void DebuggerEngine::examineModules()
+{
+}
+
+void DebuggerEngine::loadSymbols(const QString &)
+{
+}
+
+void DebuggerEngine::loadAllSymbols()
+{
+}
+
+void DebuggerEngine::requestModuleSymbols(const QString &)
+{
+}
+
+void DebuggerEngine::reloadRegisters()
+{
+}
+
+void DebuggerEngine::reloadSourceFiles()
+{
+}
+
+void DebuggerEngine::reloadFullStack()
+{
+}
+
+void DebuggerEngine::addOptionPages(QList<Core::IOptionsPage*> *) const
+{
+}
+
+unsigned DebuggerEngine::debuggerCapabilities() const
+{
+    return 0;
+}
+
+bool DebuggerEngine::isSynchronous() const
+{
+    return false;
+}
+
+QByteArray DebuggerEngine::qtNamespace() const
+{
+    return QByteArray();
+}
+
+void DebuggerEngine::createSnapshot()
+{
+}
+
+void DebuggerEngine::updateAll()
+{
+}
+
+void DebuggerEngine::attemptBreakpointSynchronization()
+{
+}
+
+bool DebuggerEngine::acceptsBreakpoint(const BreakpointData *)
+{
+    return true;
+}
+
+void DebuggerEngine::selectThread(int)
+{
+}
+
+void DebuggerEngine::assignValueInDebugger(const Internal::WatchData *, const QString &, const QVariant &)
+{
+}
+
+void DebuggerEngine::detachDebugger()
+{
+}
+
+void DebuggerEngine::executeStep()
+{
+}
+
+void DebuggerEngine::executeStepOut()
+{
+}
+
+void DebuggerEngine::executeNext()
+{
+}
+
+void DebuggerEngine::executeStepI()
+{
+}
+
+void DebuggerEngine::executeNextI()
+{
+}
+
+void DebuggerEngine::executeReturn()
+{
+}
+
+void DebuggerEngine::continueInferior()
+{
+}
+
+void DebuggerEngine::interruptInferior()
+{
+}
+
+void DebuggerEngine::executeRunToLine(const QString &, int)
+{
+}
+
+void DebuggerEngine::executeRunToFunction(const QString &)
+{
+}
+
+void DebuggerEngine::executeJumpToLine(const QString &, int)
+{
+}
+
+void DebuggerEngine::executeDebuggerCommand(const QString &)
+{
+
+}
+
+bool DebuggerEngine::isDying() const
+{
+    return targetState() == DebuggerFinished;
+}
+
 } // namespace Debugger
 
 #include "debuggerengine.moc"