OSDN Git Service

debugger: make requestMark() more robust for editors not representing files
[qt-creator-jp/qt-creator-jp.git] / src / plugins / debugger / debuggerengine.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 ** Commercial Usage
10 **
11 ** Licensees holding valid Qt Commercial licenses may use this file in
12 ** accordance with the Qt Commercial License Agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and Nokia.
15 **
16 ** GNU Lesser General Public License Usage
17 **
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** If you are unsure which license is appropriate for your use, please
26 ** contact the sales department at http://qt.nokia.com/contact.
27 **
28 **************************************************************************/
29
30 #include "debuggerengine.h"
31
32 #include "debuggeractions.h"
33 #include "debuggeragents.h"
34 #include "debuggerrunner.h"
35 #include "debuggeroutputwindow.h"
36 #include "debuggerplugin.h"
37 #include "debuggerstringutils.h"
38
39 #include "breakhandler.h"
40 #include "moduleshandler.h"
41 #include "registerhandler.h"
42 #include "snapshothandler.h"
43 #include "sourcefileshandler.h"
44 #include "stackhandler.h"
45 #include "threadshandler.h"
46 #include "watchhandler.h"
47 #include "watchutils.h"
48
49 #include <coreplugin/icore.h>
50 #include <coreplugin/editormanager/editormanager.h>
51
52 #include <projectexplorer/debugginghelper.h>
53 #include <projectexplorer/environment.h>
54 #include <projectexplorer/project.h>
55 #include <projectexplorer/projectexplorerconstants.h>
56 #include <projectexplorer/target.h>
57 #include <projectexplorer/buildconfiguration.h>
58 #include <projectexplorer/applicationrunconfiguration.h> // For LocalApplication*
59
60 #include <qt4projectmanager/qt4projectmanagerconstants.h>
61
62 #include <texteditor/itexteditor.h>
63
64 #include <utils/savedaction.h>
65 #include <utils/qtcassert.h>
66
67 #include <QtCore/QDebug>
68 #include <QtCore/QDir>
69 #include <QtCore/QFileInfo>
70 #include <QtCore/QTimer>
71
72 #include <QtGui/QAbstractItemView>
73 #include <QtGui/QStandardItemModel>
74 #include <QtGui/QAction>
75 #include <QtGui/QMenu>
76 #include <QtGui/QMessageBox>
77 #include <QtGui/QPlainTextEdit>
78 #include <QtGui/QPushButton>
79 #include <QtGui/QTextBlock>
80 #include <QtGui/QTextCursor>
81 #include <QtGui/QTextDocument>
82 #include <QtGui/QTreeWidget>
83
84
85 using namespace Core;
86 using namespace Debugger;
87 using namespace Debugger::Internal;
88 using namespace ProjectExplorer;
89 using namespace TextEditor;
90
91 //#define DEBUG_STATE 1
92 #if DEBUG_STATE
93 #   define SDEBUG(s) qDebug() << s
94 #else
95 #   define SDEBUG(s)
96 #endif
97 # define XSDEBUG(s) qDebug() << s
98
99 ///////////////////////////////////////////////////////////////////////
100 //
101 // DebuggerStartParameters
102 //
103 ///////////////////////////////////////////////////////////////////////
104
105 DebuggerStartParameters::DebuggerStartParameters()
106   : attachPID(-1),
107     useTerminal(false),
108     breakAtMain(false),
109     toolChainType(ToolChain::UNKNOWN),
110     startMode(NoStartMode)
111 {}
112
113 void DebuggerStartParameters::clear()
114 {
115     *this = DebuggerStartParameters();
116 }
117
118
119 namespace Debugger {
120
121 QDebug operator<<(QDebug d, DebuggerState state)
122 {
123     //return d << DebuggerEngine::stateName(state) << '(' << int(state) << ')';
124     return d << DebuggerEngine::stateName(state);
125 }
126
127 QDebug operator<<(QDebug str, const DebuggerStartParameters &sp)
128 {
129     QDebug nospace = str.nospace();
130     const QString sep = QString(QLatin1Char(','));
131     nospace << "executable=" << sp.executable
132             << " coreFile=" << sp.coreFile
133             << " processArgs=" << sp.processArgs.join(sep)
134             << " environment=<" << sp.environment.size() << " variables>"
135             << " workingDir=" << sp.workingDirectory
136             << " attachPID=" << sp.attachPID
137             << " useTerminal=" << sp.useTerminal
138             << " remoteChannel=" << sp.remoteChannel
139             << " remoteArchitecture=" << sp.remoteArchitecture
140             << " symbolFileName=" << sp.symbolFileName
141             << " serverStartScript=" << sp.serverStartScript
142             << " toolchain=" << sp.toolChainType << '\n';
143     return str;
144 }
145
146
147 namespace Internal {
148
149 const char *DebuggerEngine::stateName(int s)
150 {
151 #    define SN(x) case x: return #x;
152     switch (s) {
153         SN(DebuggerNotReady)
154         SN(EngineSetupRequested)
155         SN(EngineSetupOk)
156         SN(EngineSetupFailed)
157         SN(EngineRunFailed)
158         SN(InferiorSetupRequested)
159         SN(InferiorSetupFailed)
160         SN(EngineRunRequested)
161         SN(InferiorRunRequested)
162         SN(InferiorRunOk)
163         SN(InferiorRunFailed)
164         SN(InferiorUnrunnable)
165         SN(InferiorStopRequested)
166         SN(InferiorStopOk)
167         SN(InferiorStopFailed)
168         SN(InferiorShutdownRequested)
169         SN(InferiorShutdownOk)
170         SN(InferiorShutdownFailed)
171         SN(EngineShutdownRequested)
172         SN(EngineShutdownOk)
173         SN(EngineShutdownFailed)
174         SN(DebuggerFinished)
175     }
176     return "<unknown>";
177 #    undef SN
178 }
179
180
181 //////////////////////////////////////////////////////////////////////
182 //
183 // CommandHandler
184 //
185 //////////////////////////////////////////////////////////////////////
186
187 class CommandHandler : public QStandardItemModel
188 {
189 public:
190     explicit CommandHandler(DebuggerEngine *engine) : m_engine(engine) {}
191     bool setData(const QModelIndex &index, const QVariant &value, int role);
192     QAbstractItemModel *model() { return this; }
193
194 private:
195     QPointer<DebuggerEngine> m_engine;
196 };
197
198 bool CommandHandler::setData(const QModelIndex &, const QVariant &value, int role)
199 {
200     QTC_ASSERT(m_engine, qDebug() << value << role; return false);
201     m_engine->handleCommand(role, value);
202     return true;
203 }
204
205
206 //////////////////////////////////////////////////////////////////////
207 //
208 // DebuggerEnginePrivate
209 //
210 //////////////////////////////////////////////////////////////////////
211
212 class DebuggerEnginePrivate : public QObject
213 {
214     Q_OBJECT
215
216 public:
217     DebuggerEnginePrivate(DebuggerEngine *engine, const DebuggerStartParameters &sp)
218       : m_engine(engine),
219         m_runControl(0),
220         m_isActive(false),
221         m_startParameters(sp),
222         m_state(DebuggerNotReady),
223         m_lastGoodState(DebuggerNotReady),
224         m_breakHandler(engine),
225         m_commandHandler(engine),
226         m_modulesHandler(engine),
227         m_registerHandler(engine),
228         m_sourceFilesHandler(engine),
229         m_stackHandler(engine),
230         m_threadsHandler(engine),
231         m_watchHandler(engine),
232         m_disassemblerViewAgent(engine)
233     {}
234
235 public slots:
236     void breakpointSetRemoveMarginActionTriggered();
237     void breakpointEnableDisableMarginActionTriggered();
238     void handleContextMenuRequest(const QVariant &parameters);
239
240     void doSetupInferior();
241     void doRunEngine();
242     void doShutdownEngine();
243     void doShutdownInferior();
244     void doInterruptInferior();
245     void doFinishDebugger();
246
247     void queueRunEngine() {
248         m_engine->setState(EngineRunRequested);
249         m_engine->showMessage(_("QUEUE: RUN ENGINE"));
250         QTimer::singleShot(0, this, SLOT(doRunEngine()));
251     }
252
253     void queueShutdownEngine() {
254         m_engine->setState(EngineShutdownRequested);
255         m_engine->showMessage(_("QUEUE: SHUTDOWN ENGINE"));
256         QTimer::singleShot(0, this, SLOT(doShutdownEngine()));
257     }
258
259     void queueShutdownInferior() {
260         m_engine->setState(InferiorShutdownRequested);
261         m_engine->showMessage(_("QUEUE: SHUTDOWN INFERIOR"));
262         QTimer::singleShot(0, this, SLOT(doShutdownInferior()));
263     }
264
265     void queueFinishDebugger() {
266         m_engine->setState(DebuggerFinished, true);
267         m_engine->showMessage(_("QUEUE: SHUTDOWN INFERIOR"));
268         QTimer::singleShot(0, this, SLOT(doFinishDebugger()));
269     }
270
271     void raiseApplication() {
272         m_runControl->bringApplicationToForeground(m_inferiorPid);
273     }
274
275
276 public:
277     DebuggerState state() const { return m_state; }
278
279     DebuggerEngine *m_engine; // Not owned.
280     DebuggerRunControl *m_runControl;  // Not owned.
281     bool m_isActive;
282
283     DebuggerStartParameters m_startParameters;
284
285     // The current state.
286     DebuggerState m_state;
287
288     // The state we had before something unexpected happend.
289     DebuggerState m_lastGoodState;
290
291     // The state we are aiming for.
292     DebuggerState m_targetState;
293
294     qint64 m_inferiorPid;
295
296     BreakHandler m_breakHandler;
297     CommandHandler m_commandHandler;
298     ModulesHandler m_modulesHandler;
299     RegisterHandler m_registerHandler;
300     SourceFilesHandler m_sourceFilesHandler;
301     StackHandler m_stackHandler;
302     ThreadsHandler m_threadsHandler;
303     WatchHandler m_watchHandler;
304     DisassemblerViewAgent m_disassemblerViewAgent;
305 };
306
307 void DebuggerEnginePrivate::breakpointSetRemoveMarginActionTriggered()
308 {
309     QAction *act = qobject_cast<QAction *>(sender());
310     QTC_ASSERT(act, return);
311     QList<QVariant> list = act->data().toList();
312     QTC_ASSERT(list.size() == 2, return);
313     const QString fileName = list.at(0).toString();
314     const int lineNumber = list.at(1).toInt();
315     m_breakHandler.toggleBreakpoint(fileName, lineNumber);
316 }
317
318 void DebuggerEnginePrivate::breakpointEnableDisableMarginActionTriggered()
319 {
320     QAction *act = qobject_cast<QAction *>(sender());
321     QTC_ASSERT(act, return);
322     QList<QVariant> list = act->data().toList();
323     QTC_ASSERT(list.size() == 2, return);
324     const QString fileName = list.at(0).toString();
325     const int lineNumber = list.at(1).toInt();
326     m_breakHandler.toggleBreakpointEnabled(fileName, lineNumber);
327 }
328
329 void DebuggerEnginePrivate::handleContextMenuRequest(const QVariant &parameters)
330 {
331     const QList<QVariant> list = parameters.toList();
332     QTC_ASSERT(list.size() == 3, return);
333     TextEditor::ITextEditor *editor =
334         (TextEditor::ITextEditor *)(list.at(0).value<quint64>());
335     int lineNumber = list.at(1).toInt();
336     QMenu *menu = (QMenu *)(list.at(2).value<quint64>());
337
338     BreakpointData *data = 0;
339     QString position;
340     QString fileName;
341     if (editor->property("DisassemblerView").toBool()) {
342         fileName = editor->file()->fileName();
343         QString line = editor->contents()
344             .section('\n', lineNumber - 1, lineNumber - 1);
345         position = _("*") + fileName;
346         BreakpointData needle;
347         needle.bpAddress = line.left(line.indexOf(QLatin1Char(' '))).toLatin1();
348         needle.bpLineNumber = "-1";
349         data = m_breakHandler.findSimilarBreakpoint(&needle);
350     } else {
351         fileName = editor->file()->fileName();
352         position = fileName + QString(":%1").arg(lineNumber);
353         data = m_breakHandler.findBreakpoint(fileName, lineNumber);
354     }
355
356     QList<QVariant> args;
357     args.append(fileName);
358     args.append(lineNumber);
359
360     if (data) {
361         // existing breakpoint
362         QAction *act = new QAction(tr("Remove Breakpoint"), menu);
363         act->setData(args);
364         connect(act, SIGNAL(triggered()),
365             this, SLOT(breakpointSetRemoveMarginActionTriggered()));
366         menu->addAction(act);
367
368         QAction *act2;
369         if (data->enabled)
370             act2 = new QAction(tr("Disable Breakpoint"), menu);
371         else
372             act2 = new QAction(tr("Enable Breakpoint"), menu);
373         act2->setData(args);
374         connect(act2, SIGNAL(triggered()),
375             this, SLOT(breakpointEnableDisableMarginActionTriggered()));
376         menu->addAction(act2);
377     } else {
378         // non-existing
379         QAction *act = new QAction(tr("Set Breakpoint"), menu);
380         act->setData(args);
381         connect(act, SIGNAL(triggered()),
382             this, SLOT(breakpointSetRemoveMarginActionTriggered()));
383         menu->addAction(act);
384     }
385 }
386
387 //////////////////////////////////////////////////////////////////////
388 //
389 // DebuggerEngine
390 //
391 //////////////////////////////////////////////////////////////////////
392
393 DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters)
394   : d(new DebuggerEnginePrivate(this, startParameters))
395 {
396 }
397
398 DebuggerEngine::~DebuggerEngine()
399 {
400     disconnect();
401     delete d;
402 }
403
404 void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
405 {
406     showMessage(msg, StatusBar, timeout);
407 }
408
409 void DebuggerEngine::handleCommand(int role, const QVariant &value)
410 {
411     //qDebug() << "COMMAND: " << role << value;
412
413     switch (role) {
414         case RequestReloadSourceFilesRole:
415             reloadSourceFiles();
416             break;
417
418         case RequestReloadModulesRole:
419             reloadModules();
420             break;
421
422         case RequestReloadRegistersRole:
423             reloadRegisters();
424             break;
425
426         case RequestExecDetachRole:
427             detachDebugger();
428             break;
429
430         case RequestExecContinueRole:
431             continueInferior();
432             break;
433
434         case RequestExecInterruptRole:
435             requestInterruptInferior();
436             break;
437
438         case RequestExecResetRole:
439             notifyEngineIll(); // FIXME: check
440             break;
441
442         case RequestExecStepRole:
443             executeStepX();
444             break;
445
446         case RequestExecStepOutRole:
447             executeStepOutX();
448             break;
449
450         case RequestExecNextRole:
451             executeStepNextX();
452             break;
453
454         case RequestExecRunToLineRole:
455             executeRunToLine();
456             break;
457
458         case RequestExecRunToFunctionRole:
459             executeRunToFunction();
460             break;
461
462         case RequestExecReturnFromFunctionRole:
463             executeReturnX();
464             break;
465
466         case RequestExecJumpToLineRole:
467             executeJumpToLine();
468             break;
469
470         case RequestExecWatchRole:
471             addToWatchWindow();
472             break;
473
474         case RequestExecExitRole:
475             d->queueShutdownInferior();
476             break;
477
478         case RequestMakeSnapshotRole:
479             makeSnapshot();
480             break;
481
482         case RequestActivationRole:
483             setActive(value.toBool());
484             break;
485
486         case RequestExecFrameDownRole:
487             frameDown();
488             break;
489
490         case RequestExecFrameUpRole:
491             frameUp();
492             break;
493
494         case RequestOperatedByInstructionTriggeredRole:
495             gotoLocation(stackHandler()->currentFrame(), true);
496             break;
497
498         case RequestExecuteCommandRole:
499             executeDebuggerCommand(value.toString());
500             break;
501
502         case RequestToggleBreakpointRole: {
503             QList<QVariant> list = value.toList();
504             QTC_ASSERT(list.size() == 2, break);
505             const QString fileName = list.at(0).toString();
506             const int lineNumber = list.at(1).toInt();
507             breakHandler()->toggleBreakpoint(fileName, lineNumber);
508             break;
509         }
510
511         case RequestToolTipByExpressionRole: {
512             QList<QVariant> list = value.toList();
513             QTC_ASSERT(list.size() == 3, break);
514             QPoint point = list.at(0).value<QPoint>();
515             TextEditor::ITextEditor *editor = // Eeks.
516                 (TextEditor::ITextEditor *)(list.at(1).value<quint64>());
517             int pos = list.at(2).toInt();
518             setToolTipExpression(point, editor, pos);
519             break;
520         }
521
522         case RequestContextMenuRole: {
523             QList<QVariant> list = value.toList();
524             QTC_ASSERT(list.size() == 3, break);
525             d->handleContextMenuRequest(list);
526             break;
527         }
528     }
529 }
530
531 void DebuggerEngine::showModuleSymbols
532     (const QString &moduleName, const Symbols &symbols)
533 {
534     QTreeWidget *w = new QTreeWidget;
535     w->setColumnCount(3);
536     w->setRootIsDecorated(false);
537     w->setAlternatingRowColors(true);
538     w->setSortingEnabled(true);
539     w->setHeaderLabels(QStringList() << tr("Symbol") << tr("Address") << tr("Code"));
540     w->setWindowTitle(tr("Symbols in \"%1\"").arg(moduleName));
541     foreach (const Symbol &s, symbols) {
542         QTreeWidgetItem *it = new QTreeWidgetItem;
543         it->setData(0, Qt::DisplayRole, s.name);
544         it->setData(1, Qt::DisplayRole, s.address);
545         it->setData(2, Qt::DisplayRole, s.state);
546         w->addTopLevelItem(it);
547     }
548     plugin()->createNewDock(w);
549 }
550
551 void DebuggerEngine::frameUp()
552 {
553     int currentIndex = stackHandler()->currentIndex();
554     activateFrame(qMin(currentIndex + 1, stackHandler()->stackSize() - 1));
555 }
556
557 void DebuggerEngine::frameDown()
558 {
559     int currentIndex = stackHandler()->currentIndex();
560     activateFrame(qMax(currentIndex - 1, 0));
561 }
562
563 ModulesHandler *DebuggerEngine::modulesHandler() const
564 {
565     return &d->m_modulesHandler;
566 }
567
568 BreakHandler *DebuggerEngine::breakHandler() const
569 {
570     return &d->m_breakHandler;
571 }
572
573 RegisterHandler *DebuggerEngine::registerHandler() const
574 {
575     return &d->m_registerHandler;
576 }
577
578 StackHandler *DebuggerEngine::stackHandler() const
579 {
580     return &d->m_stackHandler;
581 }
582
583 ThreadsHandler *DebuggerEngine::threadsHandler() const
584 {
585     return &d->m_threadsHandler;
586 }
587
588 WatchHandler *DebuggerEngine::watchHandler() const
589 {
590     return &d->m_watchHandler;
591 }
592
593 //SnapshotHandler *DebuggerEngine::snapshotHandler() const
594 //{
595 //    return &d->m_snapshotHandler;
596 //}
597
598 SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
599 {
600     return &d->m_sourceFilesHandler;
601 }
602
603 QAbstractItemModel *DebuggerEngine::modulesModel() const
604 {
605     return d->m_modulesHandler.model();
606 }
607
608 QAbstractItemModel *DebuggerEngine::breakModel() const
609 {
610     return d->m_breakHandler.model();
611 }
612
613 QAbstractItemModel *DebuggerEngine::registerModel() const
614 {
615     return d->m_registerHandler.model();
616 }
617
618 QAbstractItemModel *DebuggerEngine::stackModel() const
619 {
620     return d->m_stackHandler.model();
621 }
622
623 QAbstractItemModel *DebuggerEngine::threadsModel() const
624 {
625     return d->m_threadsHandler.model();
626 }
627
628 QAbstractItemModel *DebuggerEngine::localsModel() const
629 {
630     return d->m_watchHandler.model(LocalsWatch);
631 }
632
633 QAbstractItemModel *DebuggerEngine::watchersModel() const
634 {
635     return d->m_watchHandler.model(WatchersWatch);
636 }
637
638 QAbstractItemModel *DebuggerEngine::returnModel() const
639 {
640     return d->m_watchHandler.model(ReturnWatch);
641 }
642
643 QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
644 {
645     return d->m_sourceFilesHandler.model();
646 }
647
648 QAbstractItemModel *DebuggerEngine::commandModel() const
649 {
650     return d->m_commandHandler.model();
651 }
652
653 void DebuggerEngine::fetchMemory(MemoryViewAgent *, QObject *,
654         quint64 addr, quint64 length)
655 {
656     Q_UNUSED(addr);
657     Q_UNUSED(length);
658 }
659
660 void DebuggerEngine::setRegisterValue(int regnr, const QString &value)
661 {
662     Q_UNUSED(regnr);
663     Q_UNUSED(value);
664 }
665
666 void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) const
667 {
668     //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
669     //    qDebug() << qPrintable(msg) << "IN STATE" << state();
670     d->m_runControl->showMessage(msg, channel);
671     plugin()->showMessage(msg, channel, timeout);
672 }
673
674 void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
675 {
676     QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
677     QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
678
679     DebuggerEngine *sessionTemplate = plugin()->sessionTemplate();
680     QTC_ASSERT(sessionTemplate, notifyEngineSetupFailed(); return);
681     QTC_ASSERT(sessionTemplate != this, notifyEngineSetupFailed(); return);
682
683     breakHandler()->initializeFromTemplate(sessionTemplate->breakHandler());
684     watchHandler()->initializeFromTemplate(sessionTemplate->watchHandler());
685
686     d->m_runControl = runControl;
687
688     QTC_ASSERT(state() == DebuggerNotReady, qDebug() << state());
689
690     d->m_inferiorPid = d->m_startParameters.attachPID > 0
691         ? d->m_startParameters.attachPID : 0;
692
693     if (d->m_startParameters.environment.empty())
694         d->m_startParameters.environment = Environment().toStringList();
695
696     if (d->m_startParameters.breakAtMain)
697         breakByFunctionMain();
698
699     const unsigned engineCapabilities = debuggerCapabilities();
700     theDebuggerAction(OperateByInstruction)
701         ->setEnabled(engineCapabilities & DisassemblerCapability);
702
703     setState(EngineSetupRequested);
704     setupEngine();
705 }
706
707 void DebuggerEngine::breakByFunctionMain()
708 {
709 #ifdef Q_OS_WIN
710     // FIXME: wrong on non-Qt based binaries
711     emit breakByFunction("qMain");
712 #else
713     emit breakByFunction("main");
714 #endif
715 }
716
717 void DebuggerEngine::breakByFunction(const QString &functionName)
718 {
719     d->m_breakHandler.breakByFunction(functionName);
720     attemptBreakpointSynchronization();
721 }
722
723 void DebuggerEngine::resetLocation()
724 {
725     d->m_disassemblerViewAgent.resetLocation();
726     d->m_stackHandler.setCurrentIndex(-1);
727     plugin()->resetLocation();
728 }
729
730 void DebuggerEngine::gotoLocation(const QString &fileName, int lineNumber, bool setMarker)
731 {
732     StackFrame frame;
733     frame.file = fileName;
734     frame.line = lineNumber;
735     gotoLocation(frame, setMarker);
736 }
737
738 void DebuggerEngine::gotoLocation(const StackFrame &frame, bool setMarker)
739 {
740     if (theDebuggerBoolSetting(OperateByInstruction) || !frame.isUsable()) {
741         if (setMarker)
742             plugin()->resetLocation();
743         d->m_disassemblerViewAgent.setFrame(frame);
744     } else {
745         plugin()->gotoLocation(frame.file, frame.line, setMarker);
746     }
747 }
748
749 void DebuggerEngine::executeStepX()
750 {
751     resetLocation();
752     if (theDebuggerBoolSetting(OperateByInstruction))
753         executeStepI();
754     else
755         executeStep();
756 }
757
758 void DebuggerEngine::executeStepOutX()
759 {
760     resetLocation();
761     executeStepOut();
762 }
763
764 void DebuggerEngine::executeStepNextX()
765 {
766     resetLocation();
767     if (theDebuggerBoolSetting(OperateByInstruction))
768         executeNextI();
769     else
770         executeNext();
771 }
772
773 void DebuggerEngine::executeReturnX()
774 {
775     resetLocation();
776     executeReturn();
777 }
778
779 static TextEditor::ITextEditor *currentTextEditor()
780 {
781     EditorManager *editorManager = EditorManager::instance();
782     if (!editorManager)
783         return 0;
784     Core::IEditor *editor = editorManager->currentEditor();
785     return qobject_cast<ITextEditor*>(editor);
786 }
787
788 void DebuggerEngine::executeRunToLine()
789 {
790     ITextEditor *textEditor = currentTextEditor();
791     QTC_ASSERT(textEditor, return);
792     QString fileName = textEditor->file()->fileName();
793     if (fileName.isEmpty())
794         return;
795     int lineNumber = textEditor->currentLine();
796     resetLocation();
797     executeRunToLine(fileName, lineNumber);
798 }
799
800 void DebuggerEngine::executeRunToFunction()
801 {
802     ITextEditor *textEditor = currentTextEditor();
803     QTC_ASSERT(textEditor, return);
804     QString fileName = textEditor->file()->fileName();
805     QPlainTextEdit *ed = qobject_cast<QPlainTextEdit*>(textEditor->widget());
806     if (!ed)
807         return;
808     QTextCursor cursor = ed->textCursor();
809     QString functionName = cursor.selectedText();
810     if (functionName.isEmpty()) {
811         const QTextBlock block = cursor.block();
812         const QString line = block.text();
813         foreach (const QString &str, line.trimmed().split('(')) {
814             QString a;
815             for (int i = str.size(); --i >= 0; ) {
816                 if (!str.at(i).isLetterOrNumber())
817                     break;
818                 a = str.at(i) + a;
819             }
820             if (!a.isEmpty()) {
821                 functionName = a;
822                 break;
823             }
824         }
825     }
826
827     if (functionName.isEmpty())
828         return;
829     resetLocation();
830     executeRunToFunction(functionName);
831 }
832
833 void DebuggerEngine::executeJumpToLine()
834 {
835     ITextEditor *textEditor = currentTextEditor();
836     QTC_ASSERT(textEditor, return);
837     QString fileName = textEditor->file()->fileName();
838     int lineNumber = textEditor->currentLine();
839     if (fileName.isEmpty())
840         return;
841     executeJumpToLine(fileName, lineNumber);
842 }
843
844 void DebuggerEngine::addToWatchWindow()
845 {
846     // Requires a selection, but that's the only case we want anyway.
847     EditorManager *editorManager = EditorManager::instance();
848     if (!editorManager)
849         return;
850     IEditor *editor = editorManager->currentEditor();
851     if (!editor)
852         return;
853     ITextEditor *textEditor = qobject_cast<ITextEditor*>(editor);
854     if (!textEditor)
855         return;
856     QTextCursor tc;
857     QPlainTextEdit *ptEdit = qobject_cast<QPlainTextEdit*>(editor->widget());
858     if (ptEdit)
859         tc = ptEdit->textCursor();
860     QString exp;
861     if (tc.hasSelection()) {
862         exp = tc.selectedText();
863     } else {
864         int line, column;
865         exp = cppExpressionAt(textEditor, tc.position(), &line, &column);
866     }
867     if (exp.isEmpty())
868         return;
869     watchHandler()->watchExpression(exp);
870 }
871
872 // Called from RunControl.
873 void DebuggerEngine::handleFinished()
874 {
875     modulesHandler()->removeAll();
876     stackHandler()->removeAll();
877     threadsHandler()->removeAll();
878     watchHandler()->cleanup();
879
880     DebuggerEngine *sessionTemplate = plugin()->sessionTemplate();
881     QTC_ASSERT(sessionTemplate != this, /**/);
882     breakHandler()->storeToTemplate(sessionTemplate->breakHandler());
883     watchHandler()->storeToTemplate(sessionTemplate->watchHandler());
884 }
885
886 const DebuggerStartParameters &DebuggerEngine::startParameters() const
887 {
888     return d->m_startParameters;
889 }
890
891 DebuggerStartParameters &DebuggerEngine::startParameters()
892 {
893     return d->m_startParameters;
894 }
895
896
897 //////////////////////////////////////////////////////////////////////
898 //
899 // Dumpers. "Custom dumpers" are a library compiled against the current
900 // Qt containing functions to evaluate values of Qt classes
901 // (such as QString, taking pointers to their addresses).
902 // The library must be loaded into the debuggee.
903 //
904 //////////////////////////////////////////////////////////////////////
905
906 bool DebuggerEngine::qtDumperLibraryEnabled() const
907 {
908     return theDebuggerBoolSetting(UseDebuggingHelpers);
909 }
910
911 QStringList DebuggerEngine::qtDumperLibraryLocations() const
912 {
913     if (theDebuggerAction(UseCustomDebuggingHelperLocation)->value().toBool()) {
914         const QString customLocation =
915             theDebuggerAction(CustomDebuggingHelperLocation)->value().toString();
916         const QString location =
917             tr("%1 (explicitly set in the Debugger Options)").arg(customLocation);
918         return QStringList(location);
919     }
920     return d->m_startParameters.dumperLibraryLocations;
921 }
922
923 void DebuggerEngine::showQtDumperLibraryWarning(const QString &details)
924 {
925     //QMessageBox dialog(d->m_mainWindow); // FIXME
926     QMessageBox dialog;
927     QPushButton *qtPref = dialog.addButton(tr("Open Qt preferences"),
928         QMessageBox::ActionRole);
929     QPushButton *helperOff = dialog.addButton(tr("Turn off helper usage"),
930         QMessageBox::ActionRole);
931     QPushButton *justContinue = dialog.addButton(tr("Continue anyway"),
932         QMessageBox::AcceptRole);
933     dialog.setDefaultButton(justContinue);
934     dialog.setWindowTitle(tr("Debugging helper missing"));
935     dialog.setText(tr("The debugger could not load the debugging helper library."));
936     dialog.setInformativeText(tr(
937         "The debugging helper is used to nicely format the values of some Qt "
938         "and Standard Library data types. "
939         "It must be compiled for each used Qt version separately. "
940         "This can be done in the Qt preferences page by selecting a Qt installation "
941         "and clicking on 'Rebuild' in the 'Debugging Helper' row."));
942     if (!details.isEmpty())
943         dialog.setDetailedText(details);
944     dialog.exec();
945     if (dialog.clickedButton() == qtPref) {
946         Core::ICore::instance()->showOptionsDialog(
947             _(Qt4ProjectManager::Constants::QT_SETTINGS_CATEGORY),
948             _(Qt4ProjectManager::Constants::QTVERSION_SETTINGS_PAGE_ID));
949     } else if (dialog.clickedButton() == helperOff) {
950         theDebuggerAction(UseDebuggingHelpers)
951             ->setValue(qVariantFromValue(false), false);
952     }
953 }
954
955 QString DebuggerEngine::qtDumperLibraryName() const
956 {
957     if (theDebuggerAction(UseCustomDebuggingHelperLocation)->value().toBool())
958         return theDebuggerAction(CustomDebuggingHelperLocation)->value().toString();
959     return startParameters().dumperLibrary;
960 }
961
962 DebuggerState DebuggerEngine::state() const
963 {
964     return d->m_state;
965 }
966
967 DebuggerState DebuggerEngine::lastGoodState() const
968 {
969     return d->m_lastGoodState;
970 }
971
972 DebuggerState DebuggerEngine::targetState() const
973 {
974     return d->m_targetState;
975 }
976
977 static bool isAllowedTransition(DebuggerState from, DebuggerState to)
978 {
979     switch (from) {
980     case DebuggerNotReady:
981         return to == EngineSetupRequested;
982
983     case EngineSetupRequested:
984         return to == EngineSetupOk || to == EngineSetupFailed;
985     case EngineSetupFailed:
986         // FIXME: In therory it's the engine's task to go into a 
987         // proper "Shutdown" state before calling notifyEngineSetupFailed
988         //return to == DebuggerFinished;
989         return to == EngineShutdownRequested;
990     case EngineSetupOk:
991         return to == InferiorSetupRequested || to == EngineShutdownRequested;
992
993     case InferiorSetupRequested:
994         return to == EngineRunRequested || to == InferiorSetupFailed;
995     case InferiorSetupFailed:
996         return to == EngineShutdownRequested;
997
998     case EngineRunRequested:
999         return to == InferiorRunRequested || to == InferiorStopRequested
1000             || to == InferiorUnrunnable || to == EngineRunFailed;
1001
1002     case EngineRunFailed:
1003         return to == InferiorShutdownRequested;
1004
1005     case InferiorRunRequested:
1006         return to == InferiorRunOk || to == InferiorRunFailed;
1007     case InferiorRunFailed:
1008         return to == InferiorStopOk;
1009     case InferiorRunOk:
1010         return to == InferiorStopRequested || to == InferiorStopOk;
1011
1012     case InferiorStopRequested:
1013         return to == InferiorStopOk || to == InferiorStopFailed;
1014     case InferiorStopOk:
1015         return to == InferiorRunRequested || to == InferiorShutdownRequested
1016             || to == InferiorStopOk;
1017     case InferiorStopFailed:
1018         return to == EngineShutdownRequested;
1019
1020     case InferiorUnrunnable:
1021         return to == InferiorShutdownRequested;
1022     case InferiorShutdownRequested:
1023         return to == InferiorShutdownOk || to == InferiorShutdownFailed;
1024     case InferiorShutdownOk:
1025         return to == EngineShutdownRequested;
1026     case InferiorShutdownFailed:
1027         return to == EngineShutdownRequested;
1028
1029     case EngineShutdownRequested:
1030         return to == EngineShutdownOk;
1031     case EngineShutdownOk:
1032         return to == DebuggerFinished;
1033     case EngineShutdownFailed:
1034         return to == DebuggerFinished;
1035
1036     case DebuggerFinished:
1037         return false;
1038     }
1039
1040     qDebug() << "UNKNOWN STATE:" << from;
1041     return false;
1042 }
1043
1044 void DebuggerEngine::notifyEngineSetupFailed()
1045 {
1046     showMessage(_("NOTE: ENGINE SETUP FAILED"));
1047     QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
1048     setState(EngineSetupFailed);
1049     d->m_runControl->startFailed();
1050     d->queueShutdownEngine();
1051 }
1052
1053 void DebuggerEngine::notifyEngineSetupOk()
1054 {
1055     showMessage(_("NOTE: ENGINE SETUP OK"));
1056     QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
1057     setState(EngineSetupOk);
1058     d->m_runControl->startSuccessful();
1059     showMessage(_("QUEUE: SETUP INFERIOR"));
1060     QTimer::singleShot(0, d, SLOT(doSetupInferior()));
1061 }
1062
1063 void DebuggerEnginePrivate::doSetupInferior()
1064 {
1065     QTC_ASSERT(state() == EngineSetupOk, qDebug() << state());
1066     m_engine->setState(InferiorSetupRequested);
1067     m_engine->showMessage(_("CALL: SETUP INFERIOR"));
1068     m_engine->setupInferior();
1069 }
1070
1071 void DebuggerEngine::notifyInferiorSetupFailed()
1072 {
1073     showMessage(_("NOTE: INFERIOR SETUP FAILED"));
1074     QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
1075     setState(InferiorSetupFailed);
1076     d->queueShutdownEngine();
1077 }
1078
1079 void DebuggerEngine::notifyInferiorSetupOk()
1080 {
1081     showMessage(_("NOTE: INFERIOR SETUP OK"));
1082     QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
1083     d->queueRunEngine();
1084 }
1085
1086 void DebuggerEnginePrivate::doRunEngine()
1087 {
1088     m_engine->showMessage(_("CALL: RUN ENGINE"));
1089     QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
1090     m_engine->runEngine();
1091 }
1092
1093 void DebuggerEngine::notifyInferiorUnrunnable()
1094 {
1095     showMessage(_("NOTE: INFERIOR UNRUNNABLE"));
1096     QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
1097     setState(InferiorUnrunnable);
1098 }
1099
1100 void DebuggerEngine::notifyEngineRunFailed()
1101 {
1102     showMessage(_("NOTE: ENGINE RUN FAILED"));
1103     QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
1104     setState(EngineRunFailed);
1105     d->queueShutdownInferior();
1106 }
1107
1108 void DebuggerEngine::notifyEngineRunAndInferiorRunOk()
1109 {
1110     showMessage(_("NOTE: ENGINE RUN AND INFERIOR RUN OK"));
1111     QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
1112     setState(InferiorRunRequested);
1113     notifyInferiorRunOk();
1114 }
1115
1116 void DebuggerEngine::notifyEngineRunAndInferiorStopOk()
1117 {
1118     showMessage(_("NOTE: ENGINE RUN AND INFERIOR STOP OK"));
1119     QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
1120     setState(InferiorStopRequested);
1121     notifyInferiorStopOk();
1122 }
1123
1124 void DebuggerEngine::notifyInferiorRunRequested()
1125 {
1126     showMessage(_("NOTE: INFERIOR RUN REQUESTED"));
1127     QTC_ASSERT(state() == InferiorStopOk, qDebug() << state());
1128     setState(InferiorRunRequested);
1129 }
1130
1131 void DebuggerEngine::notifyInferiorRunOk()
1132 {
1133     showMessage(_("NOTE: INFERIOR RUN OK"));
1134     QTC_ASSERT(state() == InferiorRunRequested, qDebug() << state());
1135     setState(InferiorRunOk);
1136 }
1137
1138 void DebuggerEngine::notifyInferiorRunFailed()
1139 {
1140     showMessage(_("NOTE: INFERIOR RUN FAILED"));
1141     QTC_ASSERT(state() == InferiorRunRequested, qDebug() << state());
1142     setState(InferiorRunFailed);
1143     setState(InferiorStopOk);
1144     if (isDying())
1145         d->queueShutdownInferior();
1146 }
1147
1148 void DebuggerEngine::notifyInferiorStopOk()
1149 {
1150     showMessage(_("NOTE: INFERIOR STOP OK"));
1151     // Ignore spurious notifications after we are set to die.
1152     if (isDying()) {
1153         showMessage(_("NOTE: ... WHILE DYING. "));
1154         // Forward state to "StopOk" if needed.
1155         if (state() == InferiorStopRequested
1156                 || state() == InferiorRunRequested
1157                 || state() == InferiorRunOk) {
1158             showMessage(_("NOTE: ... FORWARDING TO 'STOP OK'. "));
1159             setState(InferiorStopOk);
1160         }
1161         if (state() == InferiorStopOk || state() == InferiorStopFailed) {
1162             d->queueShutdownInferior();
1163         }
1164         showMessage(_("NOTE: ... IGNORING STOP MESSAGE"));
1165         return;
1166     }
1167     QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state());
1168     setState(InferiorStopOk);
1169 }
1170
1171 void DebuggerEngine::notifyInferiorSpontaneousStop()
1172 {
1173     showMessage(_("NOTE: INFERIOR SPONTANEOUES STOP"));
1174     QTC_ASSERT(state() == InferiorRunOk, qDebug() << state());
1175     setState(InferiorStopOk);
1176 }
1177
1178 void DebuggerEngine::notifyInferiorStopFailed()
1179 {
1180     showMessage(_("NOTE: INFERIOR STOP FAILED"));
1181     QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state());
1182     setState(InferiorStopFailed);
1183     d->queueShutdownEngine();
1184 }
1185
1186 void DebuggerEnginePrivate::doInterruptInferior()
1187 {
1188     QTC_ASSERT(state() == InferiorRunOk, qDebug() << state());
1189     m_engine->setState(InferiorStopRequested);
1190     m_engine->showMessage(_("CALL: INTERRUPT INFERIOR"));
1191     m_engine->interruptInferior();
1192 }
1193
1194 void DebuggerEnginePrivate::doShutdownInferior()
1195 {
1196     QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state());
1197     m_engine->resetLocation();
1198     m_targetState = DebuggerFinished;
1199     m_engine->showMessage(_("CALL: SHUTDOWN INFERIOR"));
1200     m_engine->shutdownInferior();
1201 }
1202
1203 void DebuggerEngine::notifyInferiorShutdownOk()
1204 {
1205     showMessage(_("INFERIOR SUCCESSFULLY SHUT DOWN"));
1206     QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state());
1207     d->m_lastGoodState = DebuggerNotReady; // A "neutral" value.
1208     setState(InferiorShutdownOk);
1209     d->queueShutdownEngine();
1210 }
1211
1212 void DebuggerEngine::notifyInferiorShutdownFailed()
1213 {
1214     showMessage(_("INFERIOR SHUTDOWN FAILED"));
1215     QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << this << state());
1216     setState(InferiorShutdownFailed);
1217     d->queueShutdownEngine();
1218 }
1219
1220 void DebuggerEngine::notifyInferiorIll()
1221 {
1222     showMessage(_("NOTE: INFERIOR ILL"));
1223     // This can be issued in almost any state. The inferior could still be
1224     // alive as some previous notifications might have been bogus.
1225     d->m_targetState = DebuggerFinished;
1226     d->m_lastGoodState = d->m_state;
1227     if (state() == InferiorRunRequested) {
1228         // We asked for running, but did not see a response.
1229         // Assume the inferior is dead.
1230         // FIXME: Use timeout?
1231         setState(InferiorRunFailed);
1232         setState(InferiorStopOk);
1233     }
1234     d->queueShutdownInferior();
1235 }
1236
1237 void DebuggerEnginePrivate::doShutdownEngine()
1238 {
1239     QTC_ASSERT(state() == EngineShutdownRequested
1240            || state() == InferiorShutdownOk, qDebug() << state());
1241     m_targetState = DebuggerFinished;
1242     m_engine->showMessage(_("CALL: SHUTDOWN ENGINE"));
1243     m_engine->shutdownEngine();
1244 }
1245
1246 void DebuggerEngine::notifyEngineShutdownOk()
1247 {
1248     showMessage(_("NOTE: ENGINE SHUTDOWN OK"));
1249     QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
1250     setState(EngineShutdownOk);
1251     QTimer::singleShot(0, d, SLOT(doFinishDebugger()));
1252 }
1253
1254 void DebuggerEngine::notifyEngineShutdownFailed()
1255 {
1256     showMessage(_("NOTE: ENGINE SHUTDOWN FAILED"));
1257     QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
1258     setState(EngineShutdownFailed);
1259     QTimer::singleShot(0, d, SLOT(doFinishDebugger()));
1260 }
1261
1262 void DebuggerEnginePrivate::doFinishDebugger()
1263 {
1264     m_engine->showMessage(_("NOTE: FINISH DEBUGGER"));
1265     QTC_ASSERT(state() == EngineShutdownOk
1266         || state() == EngineShutdownFailed, qDebug() << state());
1267     m_engine->resetLocation();
1268     m_engine->setState(DebuggerFinished);
1269     m_runControl->debuggingFinished();
1270 }
1271
1272 void DebuggerEngine::notifyEngineIll()
1273 {
1274     showMessage(_("NOTE: ENGINE ILL ******"));
1275     d->m_targetState = DebuggerFinished;
1276     d->m_lastGoodState = d->m_state;
1277     switch (state()) {
1278         case InferiorRunRequested:
1279         case InferiorRunOk:
1280         case InferiorStopRequested:
1281         case InferiorStopOk:
1282             qDebug() << "FORWARDING STATE TO " << InferiorShutdownFailed;
1283             setState(InferiorShutdownFailed, true);
1284             break;
1285         default:
1286             break;
1287     }
1288     d->queueShutdownEngine();
1289 }
1290
1291 void DebuggerEngine::notifyEngineSpontaneousShutdown()
1292 {
1293     showMessage(_("NOTE: ENGINE SPONTANEOUS SHUTDOWN"));
1294     d->queueFinishDebugger();
1295 }
1296
1297 void DebuggerEngine::notifyInferiorExited()
1298 {
1299     showMessage(_("NOTE: INFERIOR EXITED"));
1300     resetLocation();
1301
1302     // This can be issued in almost any state. We assume, though,
1303     // that at this point of time the inferior is not running anymore,
1304     // even if stop notification were not issued or got lost.
1305     if (state() == InferiorRunOk) {
1306         setState(InferiorStopRequested);
1307         setState(InferiorStopOk);
1308     }
1309     setState(InferiorShutdownRequested);
1310     setState(InferiorShutdownOk);
1311     d->queueShutdownEngine();
1312 }
1313
1314 void DebuggerEngine::setState(DebuggerState state, bool forced)
1315 {
1316     //qDebug() << "STATUS CHANGE: FROM " << stateName(d->m_state)
1317     //        << " TO " << stateName(state);
1318
1319     DebuggerState oldState = d->m_state;
1320     d->m_state = state;
1321
1322     QString msg = _("State changed%5 from %1(%2) to %3(%4).")
1323      .arg(stateName(oldState)).arg(oldState).arg(stateName(state)).arg(state)
1324      .arg(forced ? " BY FORCE" : "");
1325     if (!forced && !isAllowedTransition(oldState, state))
1326         qDebug() << "UNEXPECTED STATE TRANSITION: " << msg;
1327
1328     showMessage(msg, LogDebug);
1329     plugin()->updateState(this);
1330 }
1331
1332 bool DebuggerEngine::debuggerActionsEnabled() const
1333 {
1334     return debuggerActionsEnabled(d->m_state);
1335 }
1336
1337 bool DebuggerEngine::debuggerActionsEnabled(DebuggerState state)
1338 {
1339     switch (state) {
1340     case InferiorSetupRequested:
1341     case InferiorRunOk:
1342     case InferiorUnrunnable:
1343     case InferiorStopOk:
1344         return true;
1345     case InferiorStopRequested:
1346     case InferiorRunRequested:
1347     case InferiorRunFailed:
1348     case DebuggerNotReady:
1349     case EngineSetupRequested:
1350     case EngineSetupOk:
1351     case EngineSetupFailed:
1352     case EngineRunRequested:
1353     case EngineRunFailed:
1354     case InferiorSetupFailed:
1355     case InferiorStopFailed:
1356     case InferiorShutdownRequested:
1357     case InferiorShutdownOk:
1358     case InferiorShutdownFailed:
1359     case EngineShutdownRequested:
1360     case EngineShutdownOk:
1361     case EngineShutdownFailed:
1362     case DebuggerFinished:
1363         return false;
1364     }
1365     return false;
1366 }
1367
1368 void DebuggerEngine::notifyInferiorPid(qint64 pid)
1369 {
1370     showMessage(tr("Taking notice of pid %1").arg(pid));
1371     if (d->m_inferiorPid == pid)
1372         return;
1373     d->m_inferiorPid = pid;
1374     QTimer::singleShot(0, d, SLOT(raiseApplication()));
1375 }
1376
1377 qint64 DebuggerEngine::inferiorPid() const
1378 {
1379     return d->m_inferiorPid;
1380 }
1381
1382 DebuggerPlugin *DebuggerEngine::plugin() const
1383 {
1384     return DebuggerPlugin::instance();
1385 }
1386
1387 void DebuggerEngine::openFile(const QString &fileName, int lineNumber)
1388 {
1389     plugin()->gotoLocation(fileName, lineNumber, false);
1390 }
1391
1392 bool DebuggerEngine::isReverseDebugging() const
1393 {
1394     return plugin()->isReverseDebugging();
1395 }
1396
1397 bool DebuggerEngine::isActive() const
1398 {
1399     return d->m_isActive && !isSessionEngine();
1400 }
1401
1402 void DebuggerEngine::setActive(bool on)
1403 {
1404     //qDebug() << "SETTING ACTIVE" << this << on;
1405     d->m_isActive = on;
1406     //breakHandler()->updateMarkers();
1407 }
1408
1409 // called by DebuggerRunControl
1410 void DebuggerEngine::quitDebugger()
1411 {
1412     showMessage("QUIT DEBUGGER REQUESTED");
1413     d->m_targetState = DebuggerFinished;
1414     if (state() == InferiorStopOk) {
1415         d->queueShutdownInferior();
1416     } else if (state() == InferiorRunOk) {
1417         d->doInterruptInferior();
1418     } else {
1419         // FIXME: We should disable the actions connected to that
1420         notifyInferiorIll();
1421     }
1422 }
1423
1424 void DebuggerEngine::requestInterruptInferior()
1425 {
1426     d->doInterruptInferior();
1427 }
1428
1429 } // namespace Internal
1430 } // namespace Debugger
1431
1432 #include "debuggerengine.moc"