OSDN Git Service

It's 2011 now.
[qt-creator-jp/qt-creator-jp.git] / src / plugins / debugger / debuggerplugin.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 ** No Commercial Usage
10 **
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
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 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights.  These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
31 **
32 **************************************************************************/
33
34 #include "debuggerplugin.h"
35
36 #include "debuggerstartparameters.h"
37 #include "debuggeractions.h"
38 #include "debuggerconstants.h"
39 #include "debuggercore.h"
40 #include "debuggerdialogs.h"
41 #include "debuggerengine.h"
42 #include "debuggermainwindow.h"
43 #include "debuggerrunner.h"
44 #include "debuggerruncontrolfactory.h"
45 #include "debuggerstringutils.h"
46 #include "debuggertooltip.h"
47
48 #include "breakpoint.h"
49 #include "breakhandler.h"
50 #include "breakwindow.h"
51 #include "consolewindow.h"
52 #include "disassembleragent.h"
53 #include "logwindow.h"
54 #include "moduleswindow.h"
55 #include "moduleshandler.h"
56 #include "registerwindow.h"
57 #include "snapshotwindow.h"
58 #include "stackhandler.h"
59 #include "stackwindow.h"
60 #include "sourcefileswindow.h"
61 #include "threadswindow.h"
62 #include "watchhandler.h"
63 #include "watchwindow.h"
64 #include "watchutils.h"
65
66 #include "snapshothandler.h"
67 #include "threadshandler.h"
68 #include "gdb/gdboptionspage.h"
69
70 #include "ui_commonoptionspage.h"
71 #include "ui_dumperoptionpage.h"
72
73 #include <coreplugin/actionmanager/actionmanager.h>
74 #include <coreplugin/actionmanager/actioncontainer.h>
75 #include <coreplugin/actionmanager/command.h>
76 #include <coreplugin/uniqueidmanager.h>
77 #include <coreplugin/imode.h>
78 #include <coreplugin/coreconstants.h>
79 #include <coreplugin/dialogs/ioptionspage.h>
80 #include <coreplugin/editormanager/editormanager.h>
81 #include <coreplugin/findplaceholder.h>
82 #include <coreplugin/icontext.h>
83 #include <coreplugin/icore.h>
84 #include <coreplugin/imode.h>
85 #include <coreplugin/icorelistener.h>
86 #include <coreplugin/manhattanstyle.h>
87 #include <coreplugin/minisplitter.h>
88 #include <coreplugin/modemanager.h>
89
90 #include <cppeditor/cppeditorconstants.h>
91 #include <cplusplus/ModelManagerInterface.h>
92
93 #include <extensionsystem/pluginmanager.h>
94
95 #include <projectexplorer/project.h>
96 #include <projectexplorer/projectexplorer.h>
97 #include <projectexplorer/projectexplorerconstants.h>
98 #include <projectexplorer/session.h>
99 #include <projectexplorer/target.h>
100 #include <projectexplorer/toolchain.h>
101 #include <projectexplorer/toolchaintype.h>
102
103 #include <qt4projectmanager/qt4projectmanagerconstants.h>
104
105 #include <texteditor/basetexteditor.h>
106 #include <texteditor/fontsettings.h>
107 #include <texteditor/texteditorsettings.h>
108
109 #include <utils/qtcassert.h>
110 #include <utils/savedaction.h>
111 #include <utils/styledbar.h>
112
113 #include <qml/scriptconsole.h>
114
115 #include <QtCore/QTimer>
116 #include <QtCore/QtPlugin>
117 #include <QtGui/QComboBox>
118 #include <QtGui/QDockWidget>
119 #include <QtGui/QFileDialog>
120 #include <QtGui/QMenu>
121 #include <QtGui/QMessageBox>
122 #include <QtGui/QPushButton>
123 #include <QtGui/QTextBlock>
124 #include <QtGui/QTextCursor>
125 #include <QtGui/QToolButton>
126 #include <QtGui/QTreeWidget>
127
128 #include <climits>
129
130 #define DEBUG_STATE 1
131 #ifdef DEBUG_STATE
132 //#   define STATE_DEBUG(s)
133 //    do { QString msg; QTextStream ts(&msg); ts << s;
134 //      showMessage(msg, LogDebug); } while (0)
135 #   define STATE_DEBUG(s) do { qDebug() << s; } while(0)
136 #else
137 #   define STATE_DEBUG(s)
138 #endif
139
140 // Note: the Debugger process itself and any helper processes like
141 // gdbserver, the trk client etc are referred to as 'Engine',
142 // whereas the debugged process is referred to as 'Inferior'.
143 //
144 // Transitions marked by '---' are done in the individual engines.
145 // Transitions marked by '+-+' are done in the base DebuggerEngine.
146 // Transitions marked by '*' are done asynchronously.
147 // The GdbEngine->setupEngine() function is described in more detail below.
148 //
149 // The engines are responsible for local roll-back to the last
150 // acknowledged state before calling notify*Failed. I.e. before calling
151 // notifyEngineSetupFailed() any process started during setupEngine()
152 // so far must be terminated.
153 //
154 //
155 //
156 //                        DebuggerNotReady
157 //                               +
158 //                      EngineSetupRequested
159 //                               +
160 //                  (calls *Engine->setupEngine())
161 //                            |      |
162 //                            |      |
163 //                       {notify-  {notify-
164 //                        Engine-   Engine-
165 //                        SetupOk}  SetupFailed}
166 //                            +      +
167 //                            +      `+-+-+> EngineSetupFailed
168 //                            +                   +
169 //                            +    [calls RunControl->startFailed]
170 //                            +                   +
171 //                            +             DebuggerFinished
172 //                            v
173 //                      EngineSetupOk
174 //                            +
175 //             [calls RunControl->StartSuccessful]
176 //                            +
177 //                  InferiorSetupRequested
178 //                            +
179 //             (calls *Engine->setupInferior())
180 //                         |       |
181 //                         |       |
182 //                    {notify-   {notify-
183 //                     Inferior- Inferior-
184 //                     SetupOk}  SetupFailed}
185 //                         +       +
186 //                         +       ` +-+-> InferiorSetupFailed +-+-+-+-+-+->.
187 //                         +                                                +
188 //                         +                                                +
189 //                  EngineRunRequested                                      +
190 //                         +                                                +
191 //                 (calls *Engine->runEngine())                             +
192 //               /       |            |        \                            +
193 //             /         |            |          \                          +
194 //            | (core)   | (attach)   |           |                         +
195 //            |          |            |           |                         +
196 //      {notify-    {notifyER&- {notifyER&-  {notify-                       +
197 //      Inferior-     Inferior-   Inferior-  EngineRun-                     +
198 //     Unrunnable}     StopOk}     RunOk}     Failed}                       +
199 //           +           +            +           +                         +
200 //   InferiorUnrunnable  +     InferiorRunOk      +                         +
201 //                       +                        +                         +
202 //                InferiorStopOk            EngineRunFailed                 +
203 //                                                +                         v
204 //                                                 `-+-+-+-+-+-+-+-+-+-+-+>-+
205 //                                                                          +
206 //                                                                          +
207 //                       #Interrupt@InferiorRunOk#                          +
208 //                                  +                                       +
209 //                          InferiorStopRequested                           +
210 //  #SpontaneousStop                +                                       +
211 //   @InferiorRunOk#         (calls *Engine->                               +
212 //          +               interruptInferior())                            +
213 //      {notify-               |          |                                 +
214 //     Spontaneous-       {notify-    {notify-                              +
215 //      Inferior-          Inferior-   Inferior-                            +
216 //       StopOk}           StopOk}    StopFailed}                           +
217 //           +              +             +                                 +
218 //            +            +              +                                 +
219 //            InferiorStopOk              +                                 +
220 //                  +                     +                                 +
221 //                  +                    +                                  +
222 //                  +                   +                                   +
223 //        #Stop@InferiorUnrunnable#    +                                    +
224 //          #Creator Close Event#     +                                     +
225 //                       +           +                                      +
226 //                InferiorShutdownRequested                                 +
227 //                            +                                             +
228 //           (calls *Engine->shutdownInferior())                            +
229 //                         |        |                                       +
230 //                    {notify-   {notify-                                   +
231 //                     Inferior- Inferior-                                  +
232 //                  ShutdownOk}  ShutdownFailed}                            +
233 //                         +        +                                       +
234 //                         +        +                                       +
235 //  #Inferior exited#      +        +                                       +
236 //         |               +        +                                       +
237 //   {notifyInferior-      +        +                                       +
238 //      Exited}            +        +                                       +
239 //           +             +        +                                       +
240 //            +            +        +                                       +
241 //             +           +        +                                       +
242 //            InferiorShutdownOk InferiorShutdownFailed                     +
243 //                      *          *                                        +
244 //                  EngineShutdownRequested                                 +
245 //                            +                                             +
246 //           (calls *Engine->shutdownEngine())  <+-+-+-+-+-+-+-+-+-+-+-+-+-+'
247 //                         |        |
248 //                         |        |
249 //                    {notify-   {notify-
250 //                     Engine-    Engine-
251 //                  ShutdownOk}  ShutdownFailed}
252 //                         +       +
253 //            EngineShutdownOk  EngineShutdownFailed
254 //                         *       *
255 //                     DebuggerFinished
256 //
257
258
259 /* Here is a matching graph as a GraphViz graph. View it using
260  * \code
261 grep "^sg1:" debuggerplugin.cpp | cut -c5- | dot -osg1.ps -Tps && gv sg1.ps
262
263 sg1: digraph DebuggerStates {
264 sg1:   DebuggerNotReady -> EngineSetupRequested
265 sg1:   EngineSetupRequested -> EngineSetupOk [ label="notifyEngineSetupOk", style="dashed" ];
266 sg1:   EngineSetupRequested -> EngineSetupFailed [ label= "notifyEngineSetupFailed", style="dashed"];
267 sg1:   EngineSetupFailed -> DebuggerFinished [ label= "RunControl::StartFailed" ];
268 sg1:   EngineSetupOk -> InferiorSetupRequested [ label= "RunControl::StartSuccessful" ];
269 sg1:   InferiorSetupRequested -> InferiorSetupFailed [ label="notifyInferiorFailed", style="dashed" ];
270 sg1:   InferiorSetupRequested -> EngineRunRequested [ label="notifyInferiorSetupOk", style="dashed" ];
271 sg1:   InferiorSetupFailed -> EngineShutdownRequested
272 sg1:   EngineRunRequested -> InferiorUnrunnable [ label="notifyInferiorUnrunnable", style="dashed" ];
273 sg1:   EngineRunRequested -> InferiorStopOk [ label="notifyEngineRunAndInferiorStopOk", style="dashed" ];
274 sg1:   EngineRunRequested -> InferiorRunOk [ label="notifyEngineRunAndInferiorRunOk", style="dashed" ];
275 sg1:   EngineRunRequested -> EngineRunFailed [ label="notifyEngineRunFailed", style="dashed" ];
276 sg1:   EngineRunFailed -> EngineShutdownRequested
277 sg1:   InferiorRunOk -> InferiorStopOk [ label="SpontaneousStop\nnotifyInferiorSpontaneousStop", style="dashed" ];
278 sg1:   InferiorRunOk -> InferiorStopRequested [ label="User stop\nEngine::interruptInferior", style="dashed"];
279 sg1:   InferiorStopRequested -> InferiorStopOk [ label="notifyInferiorStopOk", style="dashed" ];
280 sg1:   InferiorStopRequested -> InferiorShutdownRequested  [ label="notifyInferiorStopFailed", style="dashed" ];
281 sg1:   InferiorStopOk -> InferiorRunRequested [ label="User\nEngine::continueInferior" ];
282 sg1:   InferiorRunRequested -> InferiorRunOk [ label="notifyInferiorRunOk", style="dashed"];
283 sg1:   InferiorRunRequested -> InferiorRunFailed [ label="notifyInferiorRunFailed", style="dashed"];
284 sg1:   InferiorRunFailed -> InferiorStopOk
285 sg1:   InferiorShutdownRequested -> InferiorShutdownOk [ label= "Engine::shutdownInferior\nnotifyInferiorShutdownOk", style="dashed" ];
286 sg1:   InferiorShutdownRequested -> InferiorShutdownFailed [ label="Engine::shutdownInferior\nnotifyInferiorShutdownFailed", style="dashed" ];
287 sg1:   InferiorExited -> InferiorShutdownOk [ label="notifyInferiorExited", style="dashed"];
288 sg1:   InferiorShutdownOk -> EngineShutdownRequested
289 sg1:   InferiorShutdownFailed -> EngineShutdownRequested
290 sg1:   EngineShutdownRequested -> EngineShutdownOk [ label="Engine::shutdownEngine\nnotifyEngineShutdownOk", style="dashed" ];
291 sg1:   EngineShutdownRequested -> EngineShutdownFailed  [ label="Engine::shutdownEngine\nnotifyEngineShutdownFailed", style="dashed" ];
292 sg1:   EngineShutdownOk -> DebuggerFinished  [ style = "dotted" ];
293 sg1:   EngineShutdownFailed  -> DebuggerFinished [ style = "dotted" ];
294 sg1: }
295 * \endcode */
296 // Additional signalling:    {notifyInferiorIll}   {notifyEngineIll}
297
298
299 // GdbEngine specific startup. All happens in EngineSetupRequested state
300 //
301 // Transitions marked by '---' are done in the individual adapters.
302 // Transitions marked by '+-+' are done in the GdbEngine.
303 //
304 //                  GdbEngine::setupEngine()
305 //                          +
306 //            (calls *Adapter->startAdapter())
307 //                          |      |
308 //                          |      `---> handleAdapterStartFailed()
309 //                          |                   +
310 //                          |             {notifyEngineSetupFailed}
311 //                          |
312 //                 handleAdapterStarted()
313 //                          +
314 //                 {notifyEngineSetupOk}
315 //
316 //
317 //
318 //                GdbEngine::setupInferior()
319 //                          +
320 //            (calls *Adapter->prepareInferior())
321 //                          |      |
322 //                          |      `---> handlePrepareInferiorFailed()
323 //                          |                   +
324 //                          |             {notifyInferiorSetupFailed}
325 //                          |
326 //                handleInferiorPrepared()
327 //                          +
328 //                {notifyInferiorSetupOk}
329
330
331
332
333
334 using namespace Core;
335 using namespace Debugger::Constants;
336 using namespace ProjectExplorer;
337 using namespace TextEditor;
338
339 namespace CC = Core::Constants;
340 namespace PE = ProjectExplorer::Constants;
341
342
343 namespace Debugger {
344 namespace Constants {
345
346 const char * const M_DEBUG_START_DEBUGGING = "QtCreator.Menu.Debug.StartDebugging";
347
348 const char * const STARTEXTERNAL        = "Debugger.StartExternal";
349 const char * const ATTACHEXTERNAL       = "Debugger.AttachExternal";
350 const char * const ATTACHCORE           = "Debugger.AttachCore";
351 const char * const ATTACHTCF            = "Debugger.AttachTcf";
352 const char * const ATTACHREMOTE         = "Debugger.AttachRemote";
353 const char * const ATTACHREMOTECDB      = "Debugger.AttachRemoteCDB";
354 const char * const STARTREMOTELLDB      = "Debugger.StartRemoteLLDB";
355 const char * const DETACH               = "Debugger.Detach";
356
357 const char * const RUN_TO_LINE1         = "Debugger.RunToLine1";
358 const char * const RUN_TO_LINE2         = "Debugger.RunToLine2";
359 const char * const RUN_TO_FUNCTION      = "Debugger.RunToFunction";
360 const char * const JUMP_TO_LINE1        = "Debugger.JumpToLine1";
361 const char * const JUMP_TO_LINE2        = "Debugger.JumpToLine2";
362 const char * const RETURN_FROM_FUNCTION = "Debugger.ReturnFromFunction";
363 const char * const SNAPSHOT             = "Debugger.Snapshot";
364 const char * const TOGGLE_BREAK         = "Debugger.ToggleBreak";
365 const char * const BREAK_BY_FUNCTION    = "Debugger.BreakByFunction";
366 const char * const BREAK_AT_MAIN        = "Debugger.BreakAtMain";
367 const char * const ADD_TO_WATCH1        = "Debugger.AddToWatch1";
368 const char * const ADD_TO_WATCH2        = "Debugger.AddToWatch2";
369 const char * const OPERATE_BY_INSTRUCTION  = "Debugger.OperateByInstruction";
370 const char * const FRAME_UP             = "Debugger.FrameUp";
371 const char * const FRAME_DOWN           = "Debugger.FrameDown";
372
373 #ifdef Q_WS_MAC
374 const char * const STOP_KEY                 = "Shift+Ctrl+Y";
375 const char * const RESET_KEY                = "Ctrl+Shift+F5";
376 const char * const STEP_KEY                 = "Ctrl+Shift+I";
377 const char * const STEPOUT_KEY              = "Ctrl+Shift+T";
378 const char * const NEXT_KEY                 = "Ctrl+Shift+O";
379 const char * const REVERSE_KEY              = "";
380 const char * const RUN_TO_LINE_KEY          = "Shift+F8";
381 const char * const RUN_TO_FUNCTION_KEY      = "Ctrl+F6";
382 const char * const JUMP_TO_LINE_KEY         = "Ctrl+D,Ctrl+L";
383 const char * const TOGGLE_BREAK_KEY         = "F8";
384 const char * const BREAK_BY_FUNCTION_KEY    = "Ctrl+D,Ctrl+F";
385 const char * const BREAK_AT_MAIN_KEY        = "Ctrl+D,Ctrl+M";
386 const char * const ADD_TO_WATCH_KEY         = "Ctrl+D,Ctrl+W";
387 const char * const SNAPSHOT_KEY             = "Ctrl+D,Ctrl+S";
388 #else
389 const char * const STOP_KEY                 = "Shift+F5";
390 const char * const RESET_KEY                = "Ctrl+Shift+F5";
391 const char * const STEP_KEY                 = "F11";
392 const char * const STEPOUT_KEY              = "Shift+F11";
393 const char * const NEXT_KEY                 = "F10";
394 const char * const REVERSE_KEY              = "F12";
395 const char * const RUN_TO_LINE_KEY          = "";
396 const char * const RUN_TO_FUNCTION_KEY      = "";
397 const char * const JUMP_TO_LINE_KEY         = "";
398 const char * const TOGGLE_BREAK_KEY         = "F9";
399 const char * const BREAK_BY_FUNCTION_KEY    = "";
400 const char * const BREAK_AT_MAIN_KEY        = "";
401 const char * const ADD_TO_WATCH_KEY         = "Ctrl+Alt+Q";
402 const char * const SNAPSHOT_KEY             = "Ctrl+D,Ctrl+S";
403 #endif
404
405 } // namespace Constants
406
407
408 namespace Internal {
409 void addCdb2OptionPages(QList<Core::IOptionsPage*> *);
410 } // namespace Cdb
411
412
413 namespace Internal {
414
415 // FIXME: Outdated?
416 // The createCdbEngine function takes a list of options pages it can add to.
417 // This allows for having a "enabled" toggle on the page independently
418 // of the engine. That's good for not enabling the related ActiveX control
419 // unnecessarily.
420
421 void addGdbOptionPages(QList<IOptionsPage*> *opts);
422 void addScriptOptionPages(QList<IOptionsPage*> *opts);
423 void addTcfOptionPages(QList<IOptionsPage*> *opts);
424
425 #ifdef WITH_LLDB
426 void addLldbOptionPages(QList<IOptionsPage*> *opts);
427 #endif
428
429 static SessionManager *sessionManager()
430 {
431     return ProjectExplorerPlugin::instance()->session();
432 }
433
434 static QToolButton *toolButton(QAction *action)
435 {
436     QToolButton *button = new QToolButton;
437     button->setDefaultAction(action);
438     return button;
439 }
440
441 struct AttachRemoteParameters
442 {
443     AttachRemoteParameters() : attachPid(0), winCrashEvent(0) {}
444     void clear();
445
446     quint64 attachPid;
447     QString attachTarget;  // core file name or  server:port
448     // Event handle for attaching to crashed Windows processes.
449     quint64 winCrashEvent;
450 };
451
452 void AttachRemoteParameters::clear()
453 {
454     attachPid = winCrashEvent = 0;
455     attachTarget.clear();
456 }
457
458
459 ///////////////////////////////////////////////////////////////////////
460 //
461 // DummyEngine
462 //
463 ///////////////////////////////////////////////////////////////////////
464
465 class DummyEngine : public DebuggerEngine
466 {
467     Q_OBJECT
468
469 public:
470     DummyEngine() : DebuggerEngine(DebuggerStartParameters()) {}
471     ~DummyEngine() {}
472
473     void setupEngine() {}
474     void setupInferior() {}
475     void runEngine() {}
476     void shutdownEngine() {}
477     void shutdownInferior() {}
478     void executeDebuggerCommand(const QString &) {}
479     unsigned debuggerCapabilities() const { return 0; }
480     bool acceptsBreakpoint(BreakpointId) const { return false; }
481 };
482
483 static DebuggerEngine *dummyEngine()
484 {
485     static DummyEngine dummy;
486     return &dummy;
487 }
488
489
490 ///////////////////////////////////////////////////////////////////////
491 //
492 // DebugMode
493 //
494 ///////////////////////////////////////////////////////////////////////
495
496 class DebugMode : public IMode
497 {
498 public:
499     DebugMode() : m_widget(0) { setObjectName(QLatin1String("DebugMode")); }
500
501     ~DebugMode()
502     {
503         // Make sure the editor manager does not get deleted.
504         //EditorManager::instance()->setParent(0);
505         delete m_widget;
506     }
507
508     // IMode
509     QString displayName() const { return DebuggerPlugin::tr("Debug"); }
510     QIcon icon() const { return QIcon(__(":/fancyactionbar/images/mode_Debug.png")); }
511     int priority() const { return P_MODE_DEBUG; }
512     QWidget *widget();
513     QString id() const { return MODE_DEBUG; }
514     QString type() const { return CC::MODE_EDIT_TYPE; }
515     Context context() const
516         { return Context(CC::C_EDITORMANAGER, C_DEBUGMODE, CC::C_NAVIGATION_PANE); }
517     QString contextHelpId() const { return QString(); }
518 private:
519     QWidget *m_widget;
520 };
521
522
523 ///////////////////////////////////////////////////////////////////////
524 //
525 // CommonOptionsPage
526 //
527 ///////////////////////////////////////////////////////////////////////
528
529 class CommonOptionsPage : public Core::IOptionsPage
530 {
531 public:
532     CommonOptionsPage() {}
533
534     // IOptionsPage
535     QString id() const
536         { return _(DEBUGGER_COMMON_SETTINGS_ID); }
537     QString displayName() const
538         { return QCoreApplication::translate("Debugger", DEBUGGER_COMMON_SETTINGS_NAME); }
539     QString category() const
540         { return _(DEBUGGER_SETTINGS_CATEGORY);  }
541     QString displayCategory() const
542         { return QCoreApplication::translate("Debugger", DEBUGGER_SETTINGS_TR_CATEGORY); }
543     QIcon categoryIcon() const
544         { return QIcon(QLatin1String(DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON)); }
545
546     QWidget *createPage(QWidget *parent);
547     void apply() { m_group.apply(ICore::instance()->settings()); }
548     void finish() { m_group.finish(); }
549     virtual bool matches(const QString &s) const;
550
551 private:
552     Ui::CommonOptionsPage m_ui;
553     Utils::SavedActionSet m_group;
554     QString m_searchKeywords;
555 };
556
557 QWidget *CommonOptionsPage::createPage(QWidget *parent)
558 {
559     QWidget *w = new QWidget(parent);
560     m_ui.setupUi(w);
561     m_group.clear();
562
563     m_group.insert(debuggerCore()->action(ListSourceFiles),
564         m_ui.checkBoxListSourceFiles);
565     m_group.insert(debuggerCore()->action(UseAlternatingRowColors),
566         m_ui.checkBoxUseAlternatingRowColors);
567     m_group.insert(debuggerCore()->action(UseToolTipsInMainEditor),
568         m_ui.checkBoxUseToolTipsInMainEditor);
569     m_group.insert(debuggerCore()->action(CloseBuffersOnExit),
570         m_ui.checkBoxCloseBuffersOnExit);
571     m_group.insert(debuggerCore()->action(SwitchModeOnExit),
572         m_ui.checkBoxSwitchModeOnExit);
573     m_group.insert(debuggerCore()->action(AutoDerefPointers), 0);
574     m_group.insert(debuggerCore()->action(UseToolTipsInLocalsView), 0);
575     m_group.insert(debuggerCore()->action(UseToolTipsInBreakpointsView), 0);
576     m_group.insert(debuggerCore()->action(UseAddressInBreakpointsView), 0);
577     m_group.insert(debuggerCore()->action(UseAddressInStackView), 0);
578     m_group.insert(debuggerCore()->action(MaximalStackDepth),
579         m_ui.spinBoxMaximalStackDepth);
580     m_group.insert(debuggerCore()->action(ShowStdNamespace), 0);
581     m_group.insert(debuggerCore()->action(ShowQtNamespace), 0);
582     m_group.insert(debuggerCore()->action(SortStructMembers), 0);
583     m_group.insert(debuggerCore()->action(LogTimeStamps), 0);
584     m_group.insert(debuggerCore()->action(VerboseLog), 0);
585     m_group.insert(debuggerCore()->action(BreakOnThrow), 0);
586     m_group.insert(debuggerCore()->action(BreakOnCatch), 0);
587 #ifdef Q_OS_WIN
588     Utils::SavedAction *registerAction = debuggerCore()->action(RegisterForPostMortem);
589     m_group.insert(registerAction,
590         m_ui.checkBoxRegisterForPostMortem);
591     connect(registerAction, SIGNAL(toggled(bool)),
592             m_ui.checkBoxRegisterForPostMortem, SLOT(setChecked(bool)));
593 #endif
594
595     if (m_searchKeywords.isEmpty()) {
596         QLatin1Char sep(' ');
597         QTextStream(&m_searchKeywords)
598                 << sep << m_ui.checkBoxUseAlternatingRowColors->text()
599                 << sep << m_ui.checkBoxUseToolTipsInMainEditor->text()
600                 << sep << m_ui.checkBoxListSourceFiles->text()
601 #ifdef Q_OS_WIN
602                 << sep << m_ui.checkBoxRegisterForPostMortem->text()
603 #endif
604                 << sep << m_ui.checkBoxCloseBuffersOnExit->text()
605                 << sep << m_ui.checkBoxSwitchModeOnExit->text()
606                 << sep << m_ui.labelMaximalStackDepth->text()
607                    ;
608         m_searchKeywords.remove(QLatin1Char('&'));
609     }
610 #ifndef Q_OS_WIN
611     m_ui.checkBoxRegisterForPostMortem->setVisible(false);
612 #endif
613     return w;
614 }
615
616 bool CommonOptionsPage::matches(const QString &s) const
617 {
618     return m_searchKeywords.contains(s, Qt::CaseInsensitive);
619 }
620
621 ///////////////////////////////////////////////////////////////////////
622 //
623 // DebuggingHelperOptionPage
624 //
625 ///////////////////////////////////////////////////////////////////////
626
627 static bool oxygenStyle()
628 {
629     const ManhattanStyle *ms = qobject_cast<const ManhattanStyle *>(qApp->style());
630     return ms && !qstrcmp("OxygenStyle", ms->baseStyle()->metaObject()->className());
631 }
632
633 class DebuggingHelperOptionPage : public Core::IOptionsPage
634 {
635     Q_OBJECT // Needs tr-context.
636 public:
637     DebuggingHelperOptionPage() {}
638
639     // IOptionsPage
640     QString id() const { return _("Z.DebuggingHelper"); }
641     QString displayName() const { return tr("Debugging Helper"); }
642     QString category() const { return _(DEBUGGER_SETTINGS_CATEGORY); }
643     QString displayCategory() const
644     { return QCoreApplication::translate("Debugger", DEBUGGER_SETTINGS_TR_CATEGORY); }
645     QIcon categoryIcon() const
646     { return QIcon(QLatin1String(DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON)); }
647
648     QWidget *createPage(QWidget *parent);
649     void apply() { m_group.apply(ICore::instance()->settings()); }
650     void finish() { m_group.finish(); }
651     virtual bool matches(const QString &s) const;
652
653 private:
654     Ui::DebuggingHelperOptionPage m_ui;
655     Utils::SavedActionSet m_group;
656     QString m_searchKeywords;
657 };
658
659 QWidget *DebuggingHelperOptionPage::createPage(QWidget *parent)
660 {
661     QWidget *w = new QWidget(parent);
662     m_ui.setupUi(w);
663
664     m_ui.dumperLocationChooser->setExpectedKind(Utils::PathChooser::Command);
665     m_ui.dumperLocationChooser->setPromptDialogTitle(tr("Choose DebuggingHelper Location"));
666     m_ui.dumperLocationChooser->setInitialBrowsePathBackup(
667         ICore::instance()->resourcePath() + "../../lib");
668
669     m_group.clear();
670     m_group.insert(debuggerCore()->action(UseDebuggingHelpers),
671         m_ui.debuggingHelperGroupBox);
672     m_group.insert(debuggerCore()->action(UseCustomDebuggingHelperLocation),
673         m_ui.customLocationGroupBox);
674     // Suppress Oxygen style's giving flat group boxes bold titles.
675     if (oxygenStyle())
676         m_ui.customLocationGroupBox->setStyleSheet(_("QGroupBox::title { font: ; }"));
677
678     m_group.insert(debuggerCore()->action(CustomDebuggingHelperLocation),
679         m_ui.dumperLocationChooser);
680
681     m_group.insert(debuggerCore()->action(UseCodeModel),
682         m_ui.checkBoxUseCodeModel);
683     m_group.insert(debuggerCore()->action(ShowThreadNames),
684         m_ui.checkBoxShowThreadNames);
685
686
687 #ifndef QT_DEBUG
688 #if 0
689     cmd = am->registerAction(m_dumpLogAction,
690         DUMP_LOG, globalcontext);
691     //cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+D,Ctrl+L")));
692     cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+F11")));
693     mdebug->addAction(cmd);
694 #endif
695 #endif
696
697     if (m_searchKeywords.isEmpty()) {
698         QTextStream(&m_searchKeywords)
699                 << ' ' << m_ui.debuggingHelperGroupBox->title()
700                 << ' ' << m_ui.customLocationGroupBox->title()
701                 << ' ' << m_ui.dumperLocationLabel->text()
702                 << ' ' << m_ui.checkBoxUseCodeModel->text()
703                 << ' ' << m_ui.checkBoxShowThreadNames->text();
704         m_searchKeywords.remove(QLatin1Char('&'));
705     }
706     return w;
707 }
708
709 bool DebuggingHelperOptionPage::matches(const QString &s) const
710 {
711     return m_searchKeywords.contains(s, Qt::CaseInsensitive);
712 }
713
714
715 ///////////////////////////////////////////////////////////////////////
716 //
717 // Argument parsing
718 //
719 ///////////////////////////////////////////////////////////////////////
720
721 static QString msgParameterMissing(const QString &a)
722 {
723     return DebuggerPlugin::tr("Option '%1' is missing the parameter.").arg(a);
724 }
725
726 static QString msgInvalidNumericParameter(const QString &a, const QString &number)
727 {
728     return DebuggerPlugin::tr("The parameter '%1' of option '%2' is not a number.").arg(number, a);
729 }
730
731 static bool parseArgument(QStringList::const_iterator &it,
732     const QStringList::const_iterator &cend,
733     AttachRemoteParameters *attachRemoteParameters,
734     unsigned *enabledEngines, QString *errorMessage)
735 {
736     const QString &option = *it;
737     // '-debug <pid>'
738     // '-debug <corefile>'
739     // '-debug <server:port>'
740     if (*it == _("-debug")) {
741         ++it;
742         if (it == cend) {
743             *errorMessage = msgParameterMissing(*it);
744             return false;
745         }
746         bool ok;
747         attachRemoteParameters->attachPid = it->toULongLong(&ok);
748         if (!ok)
749             attachRemoteParameters->attachTarget = *it;
750         return true;
751     }
752     // -wincrashevent <event-handle>. A handle used for
753     // a handshake when attaching to a crashed Windows process.
754     if (*it == _("-wincrashevent")) {
755         ++it;
756         if (it == cend) {
757             *errorMessage = msgParameterMissing(*it);
758             return false;
759         }
760         bool ok;
761         attachRemoteParameters->winCrashEvent = it->toULongLong(&ok);
762         if (!ok) {
763             *errorMessage = msgInvalidNumericParameter(option, *it);
764             return false;
765         }
766         return true;
767     }
768     // Engine disabling.
769     if (option == _("-disable-cdb")) {
770         *enabledEngines &= ~CdbEngineType;
771         return true;
772     }
773     if (option == _("-disable-gdb")) {
774         *enabledEngines &= ~GdbEngineType;
775         return true;
776     }
777     if (option == _("-disable-qmldb")) {
778         *enabledEngines &= ~QmlEngineType;
779         return true;
780     }
781     if (option == _("-disable-sdb")) {
782         *enabledEngines &= ~ScriptEngineType;
783         return true;
784     }
785     if (option == _("-disable-tcf")) {
786         *enabledEngines &= ~TcfEngineType;
787         return true;
788     }
789     if (option == _("-disable-lldb")) {
790         *enabledEngines &= ~LldbEngineType;
791         return true;
792     }
793
794     *errorMessage = DebuggerPlugin::tr("Invalid debugger option: %1").arg(option);
795     return false;
796 }
797
798 static bool parseArguments(const QStringList &args,
799    AttachRemoteParameters *attachRemoteParameters,
800    unsigned *enabledEngines, QString *errorMessage)
801 {
802     attachRemoteParameters->clear();
803     const QStringList::const_iterator cend = args.constEnd();
804     for (QStringList::const_iterator it = args.constBegin(); it != cend; ++it)
805         if (!parseArgument(it, cend, attachRemoteParameters, enabledEngines, errorMessage))
806             return false;
807     if (Constants::Internal::debug)
808         qDebug().nospace() << args << "engines=0x"
809             << QString::number(*enabledEngines, 16)
810             << " pid" << attachRemoteParameters->attachPid
811             << " target" << attachRemoteParameters->attachTarget << '\n';
812     return true;
813 }
814
815
816 ///////////////////////////////////////////////////////////////////////
817 //
818 // Misc
819 //
820 ///////////////////////////////////////////////////////////////////////
821
822 static bool isDebuggable(IEditor *editor)
823 {
824     // Only blacklist Qml. Whitelisting would fail on C++ code in files
825     // with strange names, more harm would be done this way.
826     //   IFile *file = editor->file();
827     //   return !(file && file->mimeType() == "application/x-qml");
828     // Nowadays, even Qml is debuggable.
829     return editor;
830 }
831
832 class ContextData
833 {
834 public:
835     ContextData() : lineNumber(0), address(0) {}
836
837 public:
838     QString fileName;
839     int lineNumber;
840     quint64 address;
841 };
842
843 } // namespace Internal
844 } // namespace Debugger
845
846 Q_DECLARE_METATYPE(Debugger::Internal::ContextData)
847
848 ///////////////////////////////////////////////////////////////////////
849 //
850 // Debugger Actions
851 //
852 ///////////////////////////////////////////////////////////////////////
853
854 namespace Debugger {
855 namespace Internal {
856
857 struct DebuggerActions
858 {
859     QAction *continueAction;
860     QAction *exitAction; // on the application output button if "Stop" is possible
861     QAction *interruptAction; // on the fat debug button if "Pause" is possible
862     QAction *undisturbableAction; // on the fat debug button if nothing can be done
863     QAction *resetAction; // FIXME: Should not be needed in a stable release
864     QAction *stepAction;
865     QAction *stepOutAction;
866     QAction *runToLineAction; // Debug menu
867     QAction *runToFunctionAction;
868     QAction *jumpToLineAction; // in the Debug menu
869     QAction *returnFromFunctionAction;
870     QAction *nextAction;
871     //QAction *snapshotAction;
872     QAction *watchAction1; // in the Debug menu
873     QAction *watchAction2; // in the text editor context menu
874     QAction *breakAction;
875     QAction *sepAction;
876     QAction *reverseDirectionAction;
877     QAction *frameUpAction;
878     QAction *frameDownAction;
879 };
880
881 static DebuggerPluginPrivate *theDebuggerCore = 0;
882
883
884 ///////////////////////////////////////////////////////////////////////
885 //
886 // DebuggerPluginPrivate
887 //
888 ///////////////////////////////////////////////////////////////////////
889
890 class DebuggerPluginPrivate : public DebuggerCore
891 {
892     Q_OBJECT
893
894 public:
895     explicit DebuggerPluginPrivate(DebuggerPlugin *plugin);
896     ~DebuggerPluginPrivate();
897
898     bool initialize(const QStringList &arguments, QString *errorMessage);
899     void extensionsInitialized();
900     void aboutToShutdown();
901
902     void connectEngine(DebuggerEngine *engine);
903     void disconnectEngine() { connectEngine(0); }
904     DebuggerEngine *currentEngine() const { return m_currentEngine; }
905
906 public slots:
907     void selectThread(int index)
908     {
909         currentEngine()->selectThread(index);
910     }
911
912     void breakpointSetMarginActionTriggered()
913     {
914         const QAction *action = qobject_cast<const QAction *>(sender());
915         QTC_ASSERT(action, return);
916         const ContextData data = action->data().value<ContextData>();
917         if (data.address)
918             toggleBreakpointByAddress(data.address);
919         else
920             toggleBreakpointByFileAndLine(data.fileName, data.lineNumber);
921     }
922
923     void breakpointRemoveMarginActionTriggered()
924     {
925         const QAction *act = qobject_cast<QAction *>(sender());
926         QTC_ASSERT(act, return);
927         m_breakHandler->removeBreakpoint(act->data().toInt());
928      }
929
930     void breakpointEnableMarginActionTriggered()
931     {
932         const QAction *act = qobject_cast<QAction *>(sender());
933         QTC_ASSERT(act, return);
934         breakHandler()->setEnabled(act->data().toInt(), true);
935     }
936
937     void breakpointDisableMarginActionTriggered()
938     {
939         const QAction *act = qobject_cast<QAction *>(sender());
940         QTC_ASSERT(act, return);
941         breakHandler()->setEnabled(act->data().toInt(), false);
942     }
943
944     void updateWatchersHeader(int section, int, int newSize)
945     {
946         m_watchersWindow->header()->resizeSection(section, newSize);
947     }
948
949     void sourceFilesDockToggled(bool on)
950     {
951         if (on && m_currentEngine->state() == InferiorStopOk)
952             m_currentEngine->reloadSourceFiles();
953     }
954
955     void modulesDockToggled(bool on)
956     {
957         if (on && m_currentEngine->state() == InferiorStopOk)
958             m_currentEngine->reloadModules();
959     }
960
961     void registerDockToggled(bool on)
962     {
963         if (on && m_currentEngine->state() == InferiorStopOk)
964             m_currentEngine->reloadRegisters();
965     }
966
967     void synchronizeBreakpoints()
968     {
969         showMessage("ATTEMPT SYNC", LogDebug);
970         for (int i = 0, n = m_snapshotHandler->size(); i != n; ++i) {
971             if (DebuggerEngine *engine = m_snapshotHandler->at(i))
972                 engine->attemptBreakpointSynchronization();
973         }
974     }
975
976     void synchronizeWatchers()
977     {
978         for (int i = 0, n = m_snapshotHandler->size(); i != n; ++i) {
979             if (DebuggerEngine *engine = m_snapshotHandler->at(i))
980                 engine->watchHandler()->updateWatchers();
981         }
982     }
983
984     void editorOpened(Core::IEditor *editor);
985     void setBusyCursor(bool busy);
986     void requestMark(TextEditor::ITextEditor *editor, int lineNumber);
987     void showToolTip(TextEditor::ITextEditor *editor,
988         const QPoint &pnt, int pos, bool *handled);
989     void requestContextMenu(TextEditor::ITextEditor *editor,
990         int lineNumber, QMenu *menu);
991
992     void activatePreviousMode();
993     void activateDebugMode();
994     void toggleBreakpoint();
995     void toggleBreakpointByFileAndLine(const QString &fileName, int lineNumber);
996     void toggleBreakpointByAddress(quint64 address);
997     void onModeChanged(Core::IMode *mode);
998     void showSettingsDialog();
999
1000     void debugProject();
1001     void startExternalApplication();
1002     void startRemoteCdbSession();
1003     void startRemoteApplication();
1004     void startRemoteEngine();
1005     void attachExternalApplication();
1006     void attachExternalApplication
1007         (qint64 pid, const QString &binary, const QString &crashParameter);
1008     bool attachCmdLine();
1009     void attachCore();
1010     void attachCore(const QString &core, const QString &exeFileName);
1011     void attachRemote(const QString &spec);
1012     void attachRemoteTcf();
1013
1014     void enableReverseDebuggingTriggered(const QVariant &value);
1015     void languagesChanged();
1016     void showStatusMessage(const QString &msg, int timeout = -1);
1017     void openMemoryEditor();
1018
1019     const CPlusPlus::Snapshot &cppCodeModelSnapshot() const;
1020
1021     void showQtDumperLibraryWarning(const QString &details);
1022     DebuggerMainWindow *mainWindow() const { return m_mainWindow; }
1023     bool isDockVisible(const QString &objectName) const
1024         { return mainWindow()->isDockVisible(objectName); }
1025
1026     bool hasSnapshots() const { return m_snapshotHandler->size(); }
1027     void createNewDock(QWidget *widget);
1028
1029     void runControlStarted(DebuggerEngine *engine);
1030     void runControlFinished(DebuggerEngine *engine);
1031     DebuggerLanguages activeLanguages() const;
1032     QString gdbBinaryForToolChain(int toolChain) const;
1033     void remoteCommand(const QStringList &options, const QStringList &);
1034
1035     bool isReverseDebugging() const;
1036
1037     BreakHandler *breakHandler() const { return m_breakHandler; }
1038     SnapshotHandler *snapshotHandler() const { return m_snapshotHandler; }
1039
1040     void setConfigValue(const QString &name, const QVariant &value);
1041     QVariant configValue(const QString &name) const;
1042
1043     DebuggerRunControl *createDebugger(const DebuggerStartParameters &sp,
1044         RunConfiguration *rc = 0);
1045     void startDebugger(RunControl *runControl);
1046     void displayDebugger(DebuggerEngine *engine, bool updateEngine = true);
1047
1048     void dumpLog();
1049     void cleanupViews();
1050     void setInitialState();
1051
1052     void fontSettingsChanged(const TextEditor::FontSettings &settings);
1053
1054     void updateState(DebuggerEngine *engine);
1055     void updateWatchersWindow();
1056     void onCurrentProjectChanged(ProjectExplorer::Project *project);
1057
1058     void clearStatusMessage();
1059
1060     void sessionLoaded();
1061     void aboutToUnloadSession();
1062     void aboutToSaveSession();
1063
1064     void executeDebuggerCommand();
1065     void scriptExpressionEntered(const QString &expression);
1066     void coreShutdown();
1067
1068 public slots:
1069     void updateDebugActions();
1070
1071     void handleExecDetach()
1072     {
1073         currentEngine()->resetLocation();
1074         currentEngine()->detachDebugger();
1075     }
1076
1077     void handleExecContinue()
1078     {
1079         currentEngine()->resetLocation();
1080         currentEngine()->continueInferior();
1081     }
1082
1083     void handleExecInterrupt()
1084     {
1085         currentEngine()->resetLocation();
1086         currentEngine()->requestInterruptInferior();
1087     }
1088
1089     void handleExecReset()
1090     {
1091         currentEngine()->resetLocation();
1092         currentEngine()->notifyEngineIll(); // FIXME: Check.
1093     }
1094
1095     void handleExecStep()
1096     {
1097         currentEngine()->resetLocation();
1098         if (boolSetting(OperateByInstruction))
1099             currentEngine()->executeStepI();
1100         else
1101             currentEngine()->executeStep();
1102     }
1103
1104     void handleExecNext()
1105     {
1106         currentEngine()->resetLocation();
1107         if (boolSetting(OperateByInstruction))
1108             currentEngine()->executeNextI();
1109         else
1110             currentEngine()->executeNext();
1111     }
1112
1113     void handleExecStepOut()
1114     {
1115         currentEngine()->resetLocation();
1116         currentEngine()->executeStepOut();
1117     }
1118
1119     void handleExecReturn()
1120     {
1121         currentEngine()->resetLocation();
1122         currentEngine()->executeReturn();
1123     }
1124
1125     void handleExecJumpToLine()
1126     {
1127         //removeTooltip();
1128         currentEngine()->resetLocation();
1129         QString fileName;
1130         int lineNumber;
1131         if (currentTextEditorPosition(&fileName, &lineNumber))
1132             currentEngine()->executeJumpToLine(fileName, lineNumber);
1133     }
1134
1135     void handleExecRunToLine()
1136     {
1137         //removeTooltip();
1138         currentEngine()->resetLocation();
1139         QString fileName;
1140         int lineNumber;
1141         if (currentTextEditorPosition(&fileName, &lineNumber))
1142             currentEngine()->executeRunToLine(fileName, lineNumber);
1143     }
1144
1145     void handleExecRunToFunction()
1146     {
1147         currentEngine()->resetLocation();
1148         ITextEditor *textEditor = currentTextEditor();
1149         QTC_ASSERT(textEditor, return);
1150         QPlainTextEdit *ed = qobject_cast<QPlainTextEdit*>(textEditor->widget());
1151         if (!ed)
1152             return;
1153         QTextCursor cursor = ed->textCursor();
1154         QString functionName = cursor.selectedText();
1155         if (functionName.isEmpty()) {
1156             const QTextBlock block = cursor.block();
1157             const QString line = block.text();
1158             foreach (const QString &str, line.trimmed().split('(')) {
1159                 QString a;
1160                 for (int i = str.size(); --i >= 0; ) {
1161                     if (!str.at(i).isLetterOrNumber())
1162                         break;
1163                     a = str.at(i) + a;
1164                 }
1165                 if (!a.isEmpty()) {
1166                     functionName = a;
1167                     break;
1168                 }
1169             }
1170         }
1171
1172         if (!functionName.isEmpty())
1173             currentEngine()->executeRunToFunction(functionName);
1174     }
1175
1176     void slotEditBreakpoint()
1177     {
1178         const QAction *act = qobject_cast<QAction *>(sender());
1179         QTC_ASSERT(act, return);
1180         const BreakpointId id = act->data().toInt();
1181         QTC_ASSERT(id > 0, return);
1182         BreakWindow::editBreakpoint(id, mainWindow());
1183     }
1184
1185     void slotRunToLine()
1186     {
1187         const QAction *action = qobject_cast<const QAction *>(sender());
1188         QTC_ASSERT(action, return);
1189         const ContextData data = action->data().value<ContextData>();
1190         currentEngine()->executeRunToLine(data.fileName, data.lineNumber);
1191     }
1192
1193     void slotJumpToLine()
1194     {
1195         const QAction *action = qobject_cast<const QAction *>(sender());
1196         QTC_ASSERT(action, return);
1197         const ContextData data = action->data().value<ContextData>();
1198         currentEngine()->executeJumpToLine(data.fileName, data.lineNumber);
1199     }
1200
1201     void handleAddToWatchWindow()
1202     {
1203         // Requires a selection, but that's the only case we want anyway.
1204         EditorManager *editorManager = EditorManager::instance();
1205         if (!editorManager)
1206             return;
1207         IEditor *editor = editorManager->currentEditor();
1208         if (!editor)
1209             return;
1210         ITextEditor *textEditor = qobject_cast<ITextEditor*>(editor);
1211         if (!textEditor)
1212             return;
1213         QTextCursor tc;
1214         QPlainTextEdit *ptEdit = qobject_cast<QPlainTextEdit*>(editor->widget());
1215         if (ptEdit)
1216             tc = ptEdit->textCursor();
1217         QString exp;
1218         if (tc.hasSelection()) {
1219             exp = tc.selectedText();
1220         } else {
1221             int line, column;
1222             exp = cppExpressionAt(textEditor, tc.position(), &line, &column);
1223         }
1224         if (exp.isEmpty())
1225             return;
1226         currentEngine()->watchHandler()->watchExpression(exp);
1227     }
1228
1229     void handleExecExit()
1230     {
1231         currentEngine()->exitDebugger();
1232     }
1233
1234     void handleFrameDown()
1235     {
1236         currentEngine()->frameDown();
1237     }
1238
1239     void handleFrameUp()
1240     {
1241         currentEngine()->frameUp();
1242     }
1243
1244     void handleOperateByInstructionTriggered(bool operateByInstructionTriggered)
1245     {
1246         // Go to source only if we have the file.
1247         if (currentEngine()->stackHandler()->currentIndex() >= 0) {
1248             const StackFrame frame = currentEngine()->stackHandler()->currentFrame();
1249             if (operateByInstructionTriggered || frame.isUsable()) {
1250                 currentEngine()->gotoLocation(Location(frame, true));
1251             }
1252         }
1253     }
1254
1255     bool isActiveDebugLanguage(int lang) const
1256     {
1257         return m_mainWindow->activeDebugLanguages() & lang;
1258     }
1259
1260     QVariant sessionValue(const QString &name);
1261     void setSessionValue(const QString &name, const QVariant &value);
1262     QIcon locationMarkIcon() const { return m_locationMarkIcon; }
1263
1264     void openTextEditor(const QString &titlePattern0, const QString &contents);
1265     void clearCppCodeModelSnapshot();
1266     void showMessage(const QString &msg, int channel, int timeout = -1);
1267
1268     Utils::SavedAction *action(int code) const;
1269     bool boolSetting(int code) const;
1270     QString stringSetting(int code) const;
1271
1272     void showModuleSymbols(const QString &moduleName, const Symbols &symbols);
1273
1274 public:
1275     DebuggerMainWindow *m_mainWindow;
1276     DebuggerRunControlFactory *m_debuggerRunControlFactory;
1277
1278     QString m_previousMode;
1279     Context m_continuableContext;
1280     Context m_interruptibleContext;
1281     Context m_undisturbableContext;
1282     Context m_finishedContext;
1283     Context m_anyContext;
1284     AttachRemoteParameters m_attachRemoteParameters;
1285
1286     QAction *m_debugAction;
1287     QAction *m_startExternalAction;
1288     QAction *m_startRemoteAction;
1289     QAction *m_startRemoteCdbAction;
1290     QAction *m_startRemoteLldbAction;
1291     QAction *m_attachExternalAction;
1292     QAction *m_attachCoreAction;
1293     QAction *m_attachTcfAction;
1294     QAction *m_detachAction;
1295     QToolButton *m_reverseToolButton;
1296
1297     QIcon m_startIcon;
1298     QIcon m_exitIcon;
1299     QIcon m_continueIcon;
1300     QIcon m_interruptIcon;
1301     QIcon m_locationMarkIcon;
1302
1303     QLabel *m_statusLabel;
1304     QComboBox *m_threadBox;
1305
1306     DebuggerActions m_actions;
1307
1308     BreakWindow *m_breakWindow;
1309     BreakHandler *m_breakHandler;
1310     //ConsoleWindow *m_consoleWindow;
1311     QTreeView *m_returnWindow;
1312     QTreeView *m_localsWindow;
1313     QTreeView *m_watchersWindow;
1314     QAbstractItemView *m_registerWindow;
1315     QAbstractItemView *m_modulesWindow;
1316     QAbstractItemView *m_snapshotWindow;
1317     SourceFilesWindow *m_sourceFilesWindow;
1318     QAbstractItemView *m_stackWindow;
1319     QAbstractItemView *m_threadsWindow;
1320     LogWindow *m_logWindow;
1321     ScriptConsole *m_scriptConsoleWindow;
1322
1323     bool m_busy;
1324     QTimer m_statusTimer;
1325     QString m_lastPermanentStatusMessage;
1326
1327     mutable CPlusPlus::Snapshot m_codeModelSnapshot;
1328     DebuggerPlugin *m_plugin;
1329
1330     SnapshotHandler *m_snapshotHandler;
1331     bool m_shuttingDown;
1332     DebuggerEngine *m_currentEngine;
1333     DebuggerSettings *m_debuggerSettings;
1334     QSettings *m_coreSettings;
1335     bool m_gdbBinariesChanged;
1336     uint m_cmdLineEnabledEngines;
1337 };
1338
1339 DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin)
1340 {
1341     qRegisterMetaType<WatchData>("WatchData");
1342     qRegisterMetaType<ContextData>("ContextData");
1343     qRegisterMetaType<DebuggerStartParameters>("DebuggerStartParameters");
1344
1345     QTC_ASSERT(!theDebuggerCore, /**/);
1346     theDebuggerCore = this;
1347
1348     m_plugin = plugin;
1349
1350     m_startRemoteCdbAction = 0;
1351     m_shuttingDown = false;
1352     m_statusLabel = 0;
1353     m_threadBox = 0;
1354
1355     m_breakWindow = 0;
1356     m_breakHandler = 0;
1357     m_returnWindow = 0;
1358     m_localsWindow = 0;
1359     m_watchersWindow = 0;
1360     m_registerWindow = 0;
1361     m_modulesWindow = 0;
1362     m_snapshotWindow = 0;
1363     m_sourceFilesWindow = 0;
1364     m_stackWindow = 0;
1365     m_threadsWindow = 0;
1366     m_logWindow = 0;
1367     m_scriptConsoleWindow = 0;
1368
1369     m_continuableContext = Context(0);
1370     m_interruptibleContext = Context(0);
1371     m_undisturbableContext = Context(0);
1372     m_finishedContext = Context(0);
1373     m_anyContext = Context(0);
1374
1375     m_mainWindow = 0;
1376     m_snapshotHandler = 0;
1377     m_currentEngine = 0;
1378     m_debuggerSettings = 0;
1379
1380     m_gdbBinariesChanged = true;
1381     m_cmdLineEnabledEngines = AllEngineTypes;
1382
1383     m_reverseToolButton = 0;
1384     m_debugAction = 0;
1385     m_startExternalAction = 0;
1386     m_startRemoteAction = 0;
1387     m_startRemoteCdbAction = 0;
1388     m_startRemoteLldbAction = 0;
1389     m_attachExternalAction = 0;
1390     m_attachCoreAction = 0;
1391     m_attachTcfAction = 0;
1392     m_detachAction = 0;
1393 }
1394
1395 DebuggerPluginPrivate::~DebuggerPluginPrivate()
1396 {
1397     delete m_debuggerSettings;
1398     m_debuggerSettings = 0;
1399
1400     delete m_mainWindow;
1401     m_mainWindow = 0;
1402
1403     delete m_snapshotHandler;
1404     m_snapshotHandler = 0;
1405 }
1406
1407 DebuggerCore *debuggerCore()
1408 {
1409     return theDebuggerCore;
1410 }
1411
1412 bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
1413     QString *errorMessage)
1414 {
1415     // Do not fail to load the whole plugin if something goes wrong here.
1416     if (!parseArguments(arguments, &m_attachRemoteParameters,
1417             &m_cmdLineEnabledEngines, errorMessage)) {
1418         *errorMessage = tr("Error evaluating command line arguments: %1")
1419             .arg(*errorMessage);
1420         qWarning("%s\n", qPrintable(*errorMessage));
1421         errorMessage->clear();
1422     }
1423
1424     // Cpp/Qml ui setup
1425     m_mainWindow = new DebuggerMainWindow;
1426
1427     return true;
1428 }
1429
1430 void DebuggerPluginPrivate::setConfigValue(const QString &name, const QVariant &value)
1431 {
1432     m_coreSettings->setValue(_("DebugMode/") + name, value);
1433 }
1434
1435 QVariant DebuggerPluginPrivate::configValue(const QString &name) const
1436 {
1437     const QVariant value = m_coreSettings->value(_("DebugMode/") + name);
1438     if (value.isValid())
1439         return value;
1440     // Legacy (pre-2.1): Check old un-namespaced-settings.
1441     return m_coreSettings->value(name);
1442 }
1443
1444 void DebuggerPluginPrivate::onCurrentProjectChanged(Project *project)
1445 {
1446     RunConfiguration *activeRc = 0;
1447     if (project) {
1448         Target *target = project->activeTarget();
1449         QTC_ASSERT(target, return);
1450         activeRc = target->activeRunConfiguration();
1451         QTC_ASSERT(activeRc, /**/);
1452     }
1453     for (int i = 0, n = m_snapshotHandler->size(); i != n; ++i) {
1454         // Run controls might be deleted during exit.
1455         if (DebuggerEngine *engine = m_snapshotHandler->at(i)) {
1456             DebuggerRunControl *runControl = engine->runControl();
1457             RunConfiguration *rc = runControl->runConfiguration();
1458             if (rc == activeRc) {
1459                 m_snapshotHandler->setCurrentIndex(i);
1460                 updateState(engine);
1461                 return;
1462             }
1463         }
1464     }
1465     // No corresponding debugger found. So we are ready to start one.
1466     ICore *core = ICore::instance();
1467     core->updateAdditionalContexts(m_anyContext, Context());
1468 }
1469
1470 void DebuggerPluginPrivate::languagesChanged()
1471 {
1472     const bool debuggerIsCPP =
1473         m_mainWindow->activeDebugLanguages() & CppLanguage;
1474     //qDebug() << "DEBUGGER IS CPP: " << debuggerIsCPP;
1475     m_startExternalAction->setVisible(debuggerIsCPP);
1476     m_attachExternalAction->setVisible(debuggerIsCPP);
1477     m_attachCoreAction->setVisible(debuggerIsCPP);
1478     m_startRemoteAction->setVisible(debuggerIsCPP);
1479     m_detachAction->setVisible(debuggerIsCPP);
1480 }
1481
1482 void DebuggerPluginPrivate::debugProject()
1483 {
1484     ProjectExplorerPlugin *pe = ProjectExplorerPlugin::instance();
1485     if (Project *pro = pe->startupProject())
1486         pe->runProject(pro, Constants::DEBUGMODE);
1487 }
1488
1489 void DebuggerPluginPrivate::startExternalApplication()
1490 {
1491     DebuggerStartParameters sp;
1492     StartExternalDialog dlg(mainWindow());
1493     dlg.setExecutableFile(
1494             configValue(_("LastExternalExecutableFile")).toString());
1495     dlg.setExecutableArguments(
1496             configValue(_("LastExternalExecutableArguments")).toString());
1497     dlg.setWorkingDirectory(
1498             configValue(_("LastExternalWorkingDirectory")).toString());
1499     if (dlg.exec() != QDialog::Accepted)
1500         return;
1501
1502     setConfigValue(_("LastExternalExecutableFile"),
1503                    dlg.executableFile());
1504     setConfigValue(_("LastExternalExecutableArguments"),
1505                    dlg.executableArguments());
1506     setConfigValue(_("LastExternalWorkingDirectory"),
1507                    dlg.workingDirectory());
1508     sp.executable = dlg.executableFile();
1509     sp.startMode = StartExternal;
1510     sp.workingDirectory = dlg.workingDirectory();
1511     if (!dlg.executableArguments().isEmpty())
1512         sp.processArgs = dlg.executableArguments();
1513     // Fixme: 1 of 3 testing hacks.
1514     if (sp.processArgs.startsWith(__("@tcf@ ")) || sp.processArgs.startsWith(__("@sym@ ")))
1515         sp.toolChainType = ToolChain_RVCT2_ARMV5;
1516
1517     if (dlg.breakAtMain()) {
1518 #ifdef Q_OS_WIN
1519         // FIXME: wrong on non-Qt based binaries
1520         breakHandler()->breakByFunction("qMain");
1521 #else
1522         breakHandler()->breakByFunction("main");
1523 #endif
1524     }
1525
1526     if (RunControl *rc = m_debuggerRunControlFactory->create(sp))
1527         startDebugger(rc);
1528 }
1529
1530 void DebuggerPluginPrivate::attachExternalApplication()
1531 {
1532     AttachExternalDialog dlg(mainWindow());
1533     if (dlg.exec() == QDialog::Accepted)
1534         attachExternalApplication(dlg.attachPID(), dlg.executable(), QString());
1535 }
1536
1537 void DebuggerPluginPrivate::attachExternalApplication
1538     (qint64 pid, const QString &binary, const QString &crashParameter)
1539 {
1540     if (pid == 0) {
1541         QMessageBox::warning(mainWindow(), tr("Warning"),
1542             tr("Cannot attach to PID 0"));
1543         return;
1544     }
1545     DebuggerStartParameters sp;
1546     sp.attachPID = pid;
1547     sp.displayName = tr("Process %1").arg(pid);
1548     sp.executable = binary;
1549     sp.crashParameter = crashParameter;
1550     sp.startMode = crashParameter.isEmpty() ? AttachExternal : AttachCrashedExternal;
1551     if (DebuggerRunControl *rc = createDebugger(sp))
1552         startDebugger(rc);
1553 }
1554
1555 void DebuggerPluginPrivate::attachCore()
1556 {
1557     AttachCoreDialog dlg(mainWindow());
1558     dlg.setExecutableFile(configValue(_("LastExternalExecutableFile")).toString());
1559     dlg.setCoreFile(configValue(_("LastExternalCoreFile")).toString());
1560     if (dlg.exec() != QDialog::Accepted)
1561         return;
1562     setConfigValue(_("LastExternalExecutableFile"), dlg.executableFile());
1563     setConfigValue(_("LastExternalCoreFile"), dlg.coreFile());
1564     attachCore(dlg.coreFile(), dlg.executableFile());
1565 }
1566
1567 void DebuggerPluginPrivate::attachCore(const QString &core, const QString &exe)
1568 {
1569     DebuggerStartParameters sp;
1570     sp.executable = exe;
1571     sp.coreFile = core;
1572     sp.displayName = tr("Core file \"%1\"").arg(core);
1573     sp.startMode = AttachCore;
1574     if (DebuggerRunControl *rc = createDebugger(sp))
1575         startDebugger(rc);
1576 }
1577
1578 void DebuggerPluginPrivate::attachRemote(const QString &spec)
1579 {
1580     // spec is:  executable@server:port@architecture
1581     DebuggerStartParameters sp;
1582     sp.executable = spec.section('@', 0, 0);
1583     sp.remoteChannel = spec.section('@', 1, 1);
1584     sp.remoteArchitecture = spec.section('@', 2, 2);
1585     sp.displayName = tr("Remote: \"%1\"").arg(sp.remoteChannel);
1586     sp.startMode = AttachToRemote;
1587     if (DebuggerRunControl *rc = createDebugger(sp))
1588         startDebugger(rc);
1589 }
1590
1591 void DebuggerPluginPrivate::startRemoteCdbSession()
1592 {
1593     const QString connectionKey = _("CdbRemoteConnection");
1594     DebuggerStartParameters sp;
1595     sp.toolChainType = ToolChain_MSVC;
1596     sp.startMode = AttachToRemote;
1597     StartRemoteCdbDialog dlg(mainWindow());
1598     QString previousConnection = configValue(connectionKey).toString();
1599     if (previousConnection.isEmpty())
1600         previousConnection = QLatin1String("localhost:1234");
1601     dlg.setConnection(previousConnection);
1602     if (dlg.exec() != QDialog::Accepted)
1603         return;
1604     sp.remoteChannel = dlg.connection();
1605     setConfigValue(connectionKey, sp.remoteChannel);
1606     if (RunControl *rc = createDebugger(sp))
1607         startDebugger(rc);
1608 }
1609
1610 void DebuggerPluginPrivate::startRemoteApplication()
1611 {
1612     DebuggerStartParameters sp;
1613     StartRemoteDialog dlg(mainWindow());
1614     QStringList arches;
1615     arches.append(_("i386:x86-64:intel"));
1616     arches.append(_("i386"));
1617     arches.append(_("arm"));
1618     QString lastUsed = configValue(_("LastRemoteArchitecture")).toString();
1619     if (!arches.contains(lastUsed))
1620         arches.prepend(lastUsed);
1621     dlg.setRemoteArchitectures(arches);
1622     QStringList gnuTargets;
1623     gnuTargets.append(_("auto"));
1624     gnuTargets.append(_("i686-linux-gnu"));
1625     gnuTargets.append(_("x86_64-linux-gnu"));
1626     gnuTargets.append(_("arm-none-linux-gnueabi"));
1627     const QString lastUsedGnuTarget
1628         = configValue(_("LastGnuTarget")).toString();
1629     if (!gnuTargets.contains(lastUsedGnuTarget))
1630         gnuTargets.prepend(lastUsedGnuTarget);
1631     dlg.setGnuTargets(gnuTargets);
1632     dlg.setRemoteChannel(
1633             configValue(_("LastRemoteChannel")).toString());
1634     dlg.setLocalExecutable(
1635             configValue(_("LastLocalExecutable")).toString());
1636     dlg.setDebugger(configValue(_("LastDebugger")).toString());
1637     dlg.setRemoteArchitecture(lastUsed);
1638     dlg.setGnuTarget(lastUsedGnuTarget);
1639     dlg.setServerStartScript(
1640             configValue(_("LastServerStartScript")).toString());
1641     dlg.setUseServerStartScript(
1642             configValue(_("LastUseServerStartScript")).toBool());
1643     dlg.setSysRoot(configValue(_("LastSysroot")).toString());
1644     if (dlg.exec() != QDialog::Accepted)
1645         return;
1646     setConfigValue(_("LastRemoteChannel"), dlg.remoteChannel());
1647     setConfigValue(_("LastLocalExecutable"), dlg.localExecutable());
1648     setConfigValue(_("LastDebugger"), dlg.debugger());
1649     setConfigValue(_("LastRemoteArchitecture"), dlg.remoteArchitecture());
1650     setConfigValue(_("LastGnuTarget"), dlg.gnuTarget());
1651     setConfigValue(_("LastServerStartScript"), dlg.serverStartScript());
1652     setConfigValue(_("LastUseServerStartScript"), dlg.useServerStartScript());
1653     setConfigValue(_("LastSysroot"), dlg.sysRoot());
1654     sp.remoteChannel = dlg.remoteChannel();
1655     sp.remoteArchitecture = dlg.remoteArchitecture();
1656     sp.gnuTarget = dlg.gnuTarget();
1657     sp.executable = dlg.localExecutable();
1658     sp.displayName = dlg.localExecutable();
1659     sp.debuggerCommand = dlg.debugger(); // Override toolchain-detection.
1660     if (!sp.debuggerCommand.isEmpty())
1661         sp.toolChainType = ToolChain_INVALID;
1662     sp.startMode = AttachToRemote;
1663     sp.useServerStartScript = dlg.useServerStartScript();
1664     sp.serverStartScript = dlg.serverStartScript();
1665     sp.sysRoot = dlg.sysRoot();
1666     if (RunControl *rc = createDebugger(sp))
1667         startDebugger(rc);
1668 }
1669
1670 void DebuggerPluginPrivate::startRemoteEngine()
1671 {
1672     DebuggerStartParameters sp;
1673     StartRemoteEngineDialog dlg(mainWindow());
1674     if (dlg.exec() != QDialog::Accepted)
1675         return;
1676
1677     sp.connParams.host = dlg.host();
1678     sp.connParams.uname = dlg.username();
1679     sp.connParams.pwd = dlg.password();
1680
1681     sp.connParams.timeout = 5;
1682     sp.connParams.authType = SshConnectionParameters::AuthByPwd;
1683     sp.connParams.port = 22;
1684     sp.connParams.proxyType = SshConnectionParameters::NoProxy;
1685
1686     sp.executable = dlg.inferiorPath();
1687     sp.serverStartScript = dlg.enginePath();
1688     sp.startMode = StartRemoteEngine;
1689     if (RunControl *rc = createDebugger(sp))
1690         startDebugger(rc);
1691 }
1692
1693 void DebuggerPluginPrivate::enableReverseDebuggingTriggered(const QVariant &value)
1694 {
1695     QTC_ASSERT(m_reverseToolButton, return);
1696     m_reverseToolButton->setVisible(value.toBool());
1697     m_actions.reverseDirectionAction->setChecked(false);
1698     m_actions.reverseDirectionAction->setEnabled(value.toBool());
1699 }
1700
1701 void DebuggerPluginPrivate::attachRemoteTcf()
1702 {
1703     DebuggerStartParameters sp;
1704     AttachTcfDialog dlg(mainWindow());
1705     QStringList arches;
1706     arches.append(_("i386:x86-64:intel"));
1707     dlg.setRemoteArchitectures(arches);
1708     dlg.setRemoteChannel(
1709             configValue(_("LastTcfRemoteChannel")).toString());
1710     dlg.setRemoteArchitecture(
1711             configValue(_("LastTcfRemoteArchitecture")).toString());
1712     dlg.setServerStartScript(
1713             configValue(_("LastTcfServerStartScript")).toString());
1714     dlg.setUseServerStartScript(
1715             configValue(_("LastTcfUseServerStartScript")).toBool());
1716     if (dlg.exec() != QDialog::Accepted)
1717         return;
1718     setConfigValue(_("LastTcfRemoteChannel"), dlg.remoteChannel());
1719     setConfigValue(_("LastTcfRemoteArchitecture"), dlg.remoteArchitecture());
1720     setConfigValue(_("LastTcfServerStartScript"), dlg.serverStartScript());
1721     setConfigValue(_("LastTcfUseServerStartScript"), dlg.useServerStartScript());
1722     sp.remoteChannel = dlg.remoteChannel();
1723     sp.remoteArchitecture = dlg.remoteArchitecture();
1724     sp.serverStartScript = dlg.serverStartScript();
1725     sp.startMode = AttachTcf;
1726     if (dlg.useServerStartScript())
1727         sp.serverStartScript = dlg.serverStartScript();
1728     if (RunControl *rc = createDebugger(sp))
1729         startDebugger(rc);
1730 }
1731
1732 bool DebuggerPluginPrivate::attachCmdLine()
1733 {
1734     if (m_attachRemoteParameters.attachPid) {
1735         showStatusMessage(tr("Attaching to PID %1.")
1736             .arg(m_attachRemoteParameters.attachPid));
1737         const QString crashParameter = m_attachRemoteParameters.winCrashEvent
1738             ? QString::number(m_attachRemoteParameters.winCrashEvent) : QString();
1739         attachExternalApplication(m_attachRemoteParameters.attachPid,
1740             QString(), crashParameter);
1741         return true;
1742     }
1743     const QString target = m_attachRemoteParameters.attachTarget;
1744     if (target.isEmpty())
1745         return false;
1746     if (target.indexOf(':') > 0) {
1747         showStatusMessage(tr("Attaching to remote server %1.").arg(target));
1748         attachRemote(target);
1749     } else {
1750         showStatusMessage(tr("Attaching to core %1.").arg(target));
1751         attachCore(target, QString());
1752     }
1753     return true;
1754 }
1755
1756 void DebuggerPluginPrivate::editorOpened(IEditor *editor)
1757 {
1758     if (!isDebuggable(editor))
1759         return;
1760     ITextEditor *textEditor = qobject_cast<ITextEditor *>(editor);
1761     if (!textEditor)
1762         return;
1763     connect(textEditor,
1764         SIGNAL(markRequested(TextEditor::ITextEditor*,int)),
1765         SLOT(requestMark(TextEditor::ITextEditor*,int)));
1766     connect(editor,
1767         SIGNAL(tooltipOverrideRequested(TextEditor::ITextEditor*,QPoint,int,bool*)),
1768         SLOT(showToolTip(TextEditor::ITextEditor*,QPoint,int,bool*)));
1769     connect(textEditor,
1770         SIGNAL(markContextMenuRequested(TextEditor::ITextEditor*,int,QMenu*)),
1771         SLOT(requestContextMenu(TextEditor::ITextEditor*,int,QMenu*)));
1772 }
1773
1774 void DebuggerPluginPrivate::requestContextMenu(ITextEditor *editor,
1775     int lineNumber, QMenu *menu)
1776 {
1777     if (!isDebuggable(editor))
1778         return;
1779
1780     BreakpointId id = BreakpointId();
1781     QString fileName;
1782     quint64 address = 0;
1783
1784     ContextData args;
1785     args.lineNumber = lineNumber;
1786
1787     if (editor->property("DisassemblerView").toBool()) {
1788         args.fileName = editor->file()->fileName();
1789         QString line = editor->contents()
1790             .section('\n', lineNumber - 1, lineNumber - 1);
1791         BreakpointResponse needle;
1792         needle.type = BreakpointByAddress;
1793         needle.address = DisassemblerAgent::addressFromDisassemblyLine(line);
1794         args.address = needle.address;
1795         needle.lineNumber = -1;
1796         id = breakHandler()->findSimilarBreakpoint(needle);
1797     } else {
1798         args.fileName = editor->file()->fileName();
1799         id = breakHandler()->findBreakpointByFileAndLine(fileName, lineNumber);
1800     }
1801
1802     if (id) {
1803         // Remove existing breakpoint.
1804         QAction *act = new QAction(menu);
1805         act->setData(int(id));
1806         act->setText(tr("Remove Breakpoint %1").arg(id));
1807         connect(act, SIGNAL(triggered()),
1808             SLOT(breakpointRemoveMarginActionTriggered()));
1809         menu->addAction(act);
1810
1811         // Enable/disable existing breakpoint.
1812         act = new QAction(menu);
1813         act->setData(int(id));
1814         if (breakHandler()->isEnabled(id)) {
1815             act->setText(tr("Disable Breakpoint %1").arg(id));
1816             connect(act, SIGNAL(triggered()),
1817                 SLOT(breakpointDisableMarginActionTriggered()));
1818         } else {
1819             act->setText(tr("Enable Breakpoint %1").arg(id));
1820             connect(act, SIGNAL(triggered()),
1821                 SLOT(breakpointEnableMarginActionTriggered()));
1822         }
1823         menu->addAction(act);
1824
1825         // Edit existing breakpoint.
1826         act = new QAction(menu);
1827         act->setText(tr("Edit Breakpoint %1...").arg(id));
1828         connect(act, SIGNAL(triggered()), SLOT(slotEditBreakpoint()));
1829         act->setData(int(id));
1830         menu->addAction(act);
1831     } else {
1832         // Handle non-existing breakpoint.
1833         const QString text = address ?
1834                     tr("Set Breakpoint at 0x%1").arg(address, 0, 16) :
1835                     tr("Set Breakpoint at line %1").arg(lineNumber);
1836         QAction *act = new QAction(text, menu);
1837         act->setData(QVariant::fromValue(args));
1838         connect(act, SIGNAL(triggered()),
1839             SLOT(breakpointSetMarginActionTriggered()));
1840         menu->addAction(act);
1841     }
1842     // Run to, jump to line below in stopped state.
1843     if (currentEngine()->state() == InferiorStopOk) {
1844         menu->addSeparator();
1845         const QString runText =
1846             DebuggerEngine::tr("Run to Line %1").arg(lineNumber);
1847         QAction *runToLineAction  = new QAction(runText, menu);
1848         runToLineAction->setData(QVariant::fromValue(args));
1849         connect(runToLineAction, SIGNAL(triggered()), SLOT(slotRunToLine()));
1850         menu->addAction(runToLineAction);
1851         if (currentEngine()->debuggerCapabilities() & JumpToLineCapability) {
1852             const QString jumpText =
1853                 DebuggerEngine::tr("Jump to Line %1").arg(lineNumber);
1854             QAction *jumpToLineAction  = new QAction(jumpText, menu);
1855             menu->addAction(runToLineAction);
1856             jumpToLineAction->setData(QVariant::fromValue(args));
1857             connect(jumpToLineAction, SIGNAL(triggered()), SLOT(slotJumpToLine()));
1858             menu->addAction(jumpToLineAction);
1859         }
1860     }
1861 }
1862
1863 void DebuggerPluginPrivate::toggleBreakpoint()
1864 {
1865     ITextEditor *textEditor = currentTextEditor();
1866     QTC_ASSERT(textEditor, return);
1867     const int lineNumber = textEditor->currentLine();
1868     if (textEditor->property("DisassemblerView").toBool()) {
1869         QString line = textEditor->contents()
1870             .section('\n', lineNumber - 1, lineNumber - 1);
1871         quint64 address = DisassemblerAgent::addressFromDisassemblyLine(line);
1872         toggleBreakpointByAddress(address);
1873     } else if (lineNumber >= 0) {
1874         toggleBreakpointByFileAndLine(textEditor->file()->fileName(), lineNumber);
1875     }
1876 }
1877
1878 void DebuggerPluginPrivate::toggleBreakpointByFileAndLine(const QString &fileName,
1879     int lineNumber)
1880 {
1881     BreakHandler *handler = m_breakHandler;
1882     BreakpointId id =
1883         handler->findBreakpointByFileAndLine(fileName, lineNumber, true);
1884     if (!id)
1885         id = handler->findBreakpointByFileAndLine(fileName, lineNumber, false);
1886
1887     if (id) {
1888         handler->removeBreakpoint(id);
1889     } else {
1890         BreakpointParameters data(BreakpointByFileAndLine);
1891         data.fileName = fileName;
1892         data.lineNumber = lineNumber;
1893         handler->appendBreakpoint(data);
1894     }
1895     synchronizeBreakpoints();
1896 }
1897
1898 void DebuggerPluginPrivate::toggleBreakpointByAddress(quint64 address)
1899 {
1900     BreakHandler *handler = m_breakHandler;
1901     BreakpointId id = handler->findBreakpointByAddress(address);
1902
1903     if (id) {
1904         handler->removeBreakpoint(id);
1905     } else {
1906         BreakpointParameters data(BreakpointByAddress);
1907         data.address = address;
1908         handler->appendBreakpoint(data);
1909     }
1910     synchronizeBreakpoints();
1911 }
1912
1913 void DebuggerPluginPrivate::requestMark(ITextEditor *editor, int lineNumber)
1914 {
1915     if (editor->property("DisassemblerView").toBool()) {
1916         QString line = editor->contents()
1917             .section('\n', lineNumber - 1, lineNumber - 1);
1918         quint64 address = DisassemblerAgent::addressFromDisassemblyLine(line);
1919         toggleBreakpointByAddress(address);
1920     } else if (editor->file()) {
1921         toggleBreakpointByFileAndLine(editor->file()->fileName(), lineNumber);
1922     }
1923 }
1924
1925 void DebuggerPluginPrivate::showToolTip(ITextEditor *editor,
1926     const QPoint &point, int pos, bool *handled)
1927 {
1928     if (!isDebuggable(editor))
1929         return;
1930     if (!boolSetting(UseToolTipsInMainEditor))
1931         return;
1932     if (!currentEngine())
1933         return;
1934     if (currentEngine()->state() != InferiorStopOk)
1935         return;
1936     QTC_ASSERT(handled, return);
1937     *handled = true;
1938     currentEngine()->setToolTipExpression(point, editor, pos);
1939 }
1940
1941 DebuggerRunControl *DebuggerPluginPrivate::createDebugger
1942     (const DebuggerStartParameters &sp, RunConfiguration *rc)
1943 {
1944     return m_debuggerRunControlFactory->create(sp, rc);
1945 }
1946
1947 // If updateEngine is set, the engine will update its threads/modules and so forth.
1948 void DebuggerPluginPrivate::displayDebugger(DebuggerEngine *engine, bool updateEngine)
1949 {
1950     QTC_ASSERT(engine, return);
1951     disconnectEngine();
1952     connectEngine(engine);
1953     if (updateEngine)
1954         engine->updateAll();
1955     engine->updateViews();
1956 }
1957
1958 void DebuggerPluginPrivate::startDebugger(RunControl *rc)
1959 {
1960     QTC_ASSERT(rc, return);
1961     ProjectExplorerPlugin::instance()->startRunControl(rc, Constants::DEBUGMODE);
1962 }
1963
1964
1965 void DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine)
1966 {
1967     if (!engine)
1968         engine = dummyEngine();
1969
1970     if (m_currentEngine == engine)
1971         return;
1972
1973     if (m_currentEngine)
1974         m_currentEngine->resetLocation();
1975     m_currentEngine = engine;
1976
1977     m_localsWindow->setModel(engine->localsModel());
1978     m_modulesWindow->setModel(engine->modulesModel());
1979     m_registerWindow->setModel(engine->registerModel());
1980     m_returnWindow->setModel(engine->returnModel());
1981     m_sourceFilesWindow->setModel(engine->sourceFilesModel());
1982     m_stackWindow->setModel(engine->stackModel());
1983     m_threadsWindow->setModel(engine->threadsModel());
1984     m_threadBox->setModel(engine->threadsModel());
1985     m_threadBox->setModelColumn(ThreadData::NameColumn);
1986     m_watchersWindow->setModel(engine->watchersModel());
1987 }
1988
1989 static void changeFontSize(QWidget *widget, qreal size)
1990 {
1991     QFont font = widget->font();
1992     font.setPointSizeF(size);
1993     widget->setFont(font);
1994 }
1995
1996 void DebuggerPluginPrivate::fontSettingsChanged
1997     (const TextEditor::FontSettings &settings)
1998 {
1999     qreal size = settings.fontZoom() * settings.fontSize() / 100.;
2000     changeFontSize(m_breakWindow, size);
2001     changeFontSize(m_logWindow, size);
2002     changeFontSize(m_localsWindow, size);
2003     changeFontSize(m_modulesWindow, size);
2004     //changeFontSize(m_consoleWindow, size);
2005     changeFontSize(m_registerWindow, size);
2006     changeFontSize(m_returnWindow, size);
2007     changeFontSize(m_sourceFilesWindow, size);
2008     changeFontSize(m_stackWindow, size);
2009     changeFontSize(m_threadsWindow, size);
2010     changeFontSize(m_watchersWindow, size);
2011 }
2012
2013 void DebuggerPluginPrivate::cleanupViews()
2014 {
2015     m_actions.reverseDirectionAction->setChecked(false);
2016     m_actions.reverseDirectionAction->setEnabled(false);
2017     hideDebuggerToolTip();
2018
2019     if (!boolSetting(CloseBuffersOnExit))
2020         return;
2021
2022     EditorManager *editorManager = EditorManager::instance();
2023     QTC_ASSERT(editorManager, return);
2024     QList<IEditor *> toClose;
2025     foreach (IEditor *editor, editorManager->openedEditors()) {
2026         if (editor->property(Constants::OPENED_BY_DEBUGGER).toBool()) {
2027             // Close disassembly views. Close other opened files
2028             // if they are not modified and not current editor.
2029             if (editor->property(Constants::OPENED_WITH_DISASSEMBLY).toBool()
2030                     || (!editor->file()->isModified()
2031                         && editor != editorManager->currentEditor())) {
2032                 toClose.append(editor);
2033             } else {
2034                 editor->setProperty(Constants::OPENED_BY_DEBUGGER, false);
2035             }
2036         }
2037     }
2038     editorManager->closeEditors(toClose);
2039 }
2040
2041 void DebuggerPluginPrivate::setBusyCursor(bool busy)
2042 {
2043     //STATE_DEBUG("BUSY FROM: " << m_busy << " TO: " << busy);
2044     if (busy == m_busy)
2045         return;
2046     m_busy = busy;
2047     QCursor cursor(busy ? Qt::BusyCursor : Qt::ArrowCursor);
2048     m_breakWindow->setCursor(cursor);
2049     //m_consoleWindow->setCursor(cursor);
2050     m_localsWindow->setCursor(cursor);
2051     m_modulesWindow->setCursor(cursor);
2052     m_logWindow->setCursor(cursor);
2053     m_registerWindow->setCursor(cursor);
2054     m_returnWindow->setCursor(cursor);
2055     m_sourceFilesWindow->setCursor(cursor);
2056     m_stackWindow->setCursor(cursor);
2057     m_threadsWindow->setCursor(cursor);
2058     m_watchersWindow->setCursor(cursor);
2059     m_snapshotWindow->setCursor(cursor);
2060     m_scriptConsoleWindow->setCursor(cursor);
2061 }
2062
2063 void DebuggerPluginPrivate::setInitialState()
2064 {
2065     m_watchersWindow->setVisible(false);
2066     m_returnWindow->setVisible(false);
2067     setBusyCursor(false);
2068     m_actions.reverseDirectionAction->setChecked(false);
2069     m_actions.reverseDirectionAction->setEnabled(false);
2070     hideDebuggerToolTip();
2071
2072     m_startExternalAction->setEnabled(true);
2073     m_attachExternalAction->setEnabled(true);
2074 #ifdef Q_OS_WIN
2075     m_attachCoreAction->setEnabled(false);
2076 #else
2077     m_attachCoreAction->setEnabled(true);
2078 #endif
2079     m_startRemoteAction->setEnabled(true);
2080     m_detachAction->setEnabled(false);
2081
2082     m_actions.watchAction1->setEnabled(true);
2083     m_actions.watchAction2->setEnabled(true);
2084     m_actions.breakAction->setEnabled(true);
2085     //m_actions.snapshotAction->setEnabled(false);
2086     action(OperateByInstruction)->setEnabled(false);
2087
2088     m_actions.exitAction->setEnabled(false);
2089     m_actions.resetAction->setEnabled(false);
2090
2091     m_actions.stepAction->setEnabled(false);
2092     m_actions.stepOutAction->setEnabled(false);
2093     m_actions.runToLineAction->setEnabled(false);
2094     m_actions.runToFunctionAction->setEnabled(false);
2095     m_actions.returnFromFunctionAction->setEnabled(false);
2096     m_actions.jumpToLineAction->setEnabled(false);
2097     m_actions.nextAction->setEnabled(false);
2098
2099     action(AutoDerefPointers)->setEnabled(true);
2100     action(ExpandStack)->setEnabled(false);
2101     action(ExecuteCommand)->setEnabled(false);
2102
2103     m_scriptConsoleWindow->setEnabled(false);
2104 }
2105
2106 void DebuggerPluginPrivate::updateWatchersWindow()
2107 {
2108     m_watchersWindow->setVisible(
2109         m_watchersWindow->model()->rowCount(QModelIndex()) > 0);
2110     m_returnWindow->setVisible(
2111         m_returnWindow->model()->rowCount(QModelIndex()) > 0);
2112 }
2113
2114 void DebuggerPluginPrivate::updateState(DebuggerEngine *engine)
2115 {
2116     QTC_ASSERT(engine, return);
2117     QTC_ASSERT(m_watchersWindow->model(), return);
2118     QTC_ASSERT(m_returnWindow->model(), return);
2119     QTC_ASSERT(!engine->isSlaveEngine(), return);
2120
2121     m_threadBox->setCurrentIndex(engine->threadsHandler()->currentThread());
2122
2123     updateWatchersWindow();
2124
2125     const DebuggerState state = engine->state();
2126     //showMessage(QString("PLUGIN SET STATE: ")
2127     //    + DebuggerEngine::stateName(state), LogStatus);
2128     //qDebug() << "PLUGIN SET STATE: " << state;
2129
2130     static DebuggerState previousState = DebuggerNotReady;
2131     if (state == previousState)
2132         return;
2133
2134     bool actionsEnabled = DebuggerEngine::debuggerActionsEnabled(state);
2135
2136     ICore *core = ICore::instance();
2137     ActionManager *am = core->actionManager();
2138     if (state == DebuggerNotReady) {
2139         QTC_ASSERT(false, /* We use the Core m_debugAction here */);
2140         // F5 starts debugging. It is "startable".
2141         m_actions.interruptAction->setEnabled(false);
2142         m_actions.continueAction->setEnabled(false);
2143         m_actions.exitAction->setEnabled(false);
2144         am->command(Constants::STOP)->setKeySequence(QKeySequence());
2145         am->command(Constants::DEBUG)->setKeySequence(QKeySequence(DEBUG_KEY));
2146         core->updateAdditionalContexts(m_anyContext, Context());
2147     } else if (state == InferiorStopOk) {
2148         // F5 continues, Shift-F5 kills. It is "continuable".
2149         m_actions.interruptAction->setEnabled(false);
2150         m_actions.continueAction->setEnabled(true);
2151         m_actions.exitAction->setEnabled(true);
2152         am->command(Constants::STOP)->setKeySequence(QKeySequence(STOP_KEY));
2153         am->command(Constants::DEBUG)->setKeySequence(QKeySequence(DEBUG_KEY));
2154         core->updateAdditionalContexts(m_anyContext, m_continuableContext);
2155     } else if (state == InferiorRunOk) {
2156         // Shift-F5 interrupts. It is also "interruptible".
2157         m_actions.interruptAction->setEnabled(true);
2158         m_actions.continueAction->setEnabled(false);
2159         m_actions.exitAction->setEnabled(false);
2160         am->command(Constants::STOP)->setKeySequence(QKeySequence());
2161         am->command(Constants::DEBUG)->setKeySequence(QKeySequence(STOP_KEY));
2162         core->updateAdditionalContexts(m_anyContext, m_interruptibleContext);
2163     } else if (state == DebuggerFinished) {
2164         // We don't want to do anything anymore.
2165         m_actions.interruptAction->setEnabled(false);
2166         m_actions.continueAction->setEnabled(false);
2167         m_actions.exitAction->setEnabled(false);
2168         am->command(Constants::STOP)->setKeySequence(QKeySequence());
2169         am->command(Constants::DEBUG)->setKeySequence(QKeySequence(DEBUG_KEY));
2170         //core->updateAdditionalContexts(m_anyContext, m_finishedContext);
2171         m_codeModelSnapshot = CPlusPlus::Snapshot();
2172         core->updateAdditionalContexts(m_anyContext, Context());
2173         setBusyCursor(false);
2174         cleanupViews();
2175     } else if (state == InferiorUnrunnable) {
2176         // We don't want to do anything anymore.
2177         m_actions.interruptAction->setEnabled(false);
2178         m_actions.continueAction->setEnabled(false);
2179         m_actions.exitAction->setEnabled(true);
2180         am->command(Constants::STOP)->setKeySequence(QKeySequence(STOP_KEY));
2181         am->command(Constants::DEBUG)->setKeySequence(QKeySequence(STOP_KEY));
2182         core->updateAdditionalContexts(m_anyContext, m_finishedContext);
2183     } else {
2184         // Everything else is "undisturbable".
2185         m_actions.interruptAction->setEnabled(false);
2186         m_actions.continueAction->setEnabled(false);
2187         m_actions.exitAction->setEnabled(false);
2188         am->command(Constants::STOP)->setKeySequence(QKeySequence());
2189         am->command(Constants::DEBUG)->setKeySequence(QKeySequence());
2190         core->updateAdditionalContexts(m_anyContext, m_undisturbableContext);
2191     }
2192
2193     m_startExternalAction->setEnabled(true);
2194     m_attachExternalAction->setEnabled(true);
2195 #ifdef Q_OS_WIN
2196     m_attachCoreAction->setEnabled(false);
2197 #else
2198     m_attachCoreAction->setEnabled(true);
2199 #endif
2200     m_startRemoteAction->setEnabled(true);
2201
2202     const bool isCore = engine->startParameters().startMode == AttachCore;
2203     const bool stopped = state == InferiorStopOk;
2204     const bool detachable = stopped && !isCore;
2205     m_detachAction->setEnabled(detachable);
2206
2207     if (stopped)
2208         QApplication::alert(mainWindow(), 3000);
2209
2210     const uint caps = engine->debuggerCapabilities();
2211     const bool canReverse = (caps & ReverseSteppingCapability)
2212                 && boolSetting(EnableReverseDebugging);
2213     m_actions.reverseDirectionAction->setEnabled(canReverse);
2214
2215     m_actions.watchAction1->setEnabled(true);
2216     m_actions.watchAction2->setEnabled(true);
2217     m_actions.breakAction->setEnabled(true);
2218     //m_actions.snapshotAction->setEnabled(stopped && (caps & SnapshotCapability));
2219
2220     action(OperateByInstruction)->setEnabled(stopped || isCore);
2221
2222     m_actions.resetAction->setEnabled(state != DebuggerNotReady
2223                                       && state != DebuggerFinished);
2224
2225     m_actions.stepAction->setEnabled(stopped);
2226     m_actions.stepOutAction->setEnabled(stopped);
2227     m_actions.runToLineAction->setEnabled(stopped);
2228     m_actions.runToFunctionAction->setEnabled(stopped);
2229     m_actions.returnFromFunctionAction->
2230         setEnabled(stopped && (caps & ReturnFromFunctionCapability));
2231
2232     const bool canJump = stopped && (caps & JumpToLineCapability);
2233     m_actions.jumpToLineAction->setEnabled(canJump);
2234
2235     m_actions.nextAction->setEnabled(stopped);
2236
2237     const bool canDeref = actionsEnabled && (caps & AutoDerefPointersCapability);
2238     action(AutoDerefPointers)->setEnabled(canDeref);
2239     action(AutoDerefPointers)->setEnabled(true);
2240     action(ExpandStack)->setEnabled(actionsEnabled);
2241     action(ExecuteCommand)->setEnabled(state == InferiorStopOk);
2242
2243     const bool notbusy = state == InferiorStopOk
2244         || state == DebuggerNotReady
2245         || state == DebuggerFinished
2246         || state == InferiorUnrunnable;
2247     setBusyCursor(!notbusy);
2248
2249     m_scriptConsoleWindow->setEnabled(stopped);
2250 }
2251
2252 void DebuggerPluginPrivate::updateDebugActions()
2253 {
2254     ProjectExplorerPlugin *pe = ProjectExplorerPlugin::instance();
2255     Project *project = pe->startupProject();
2256     m_debugAction->setEnabled(pe->canRun(project, Constants::DEBUGMODE));
2257 }
2258
2259 void DebuggerPluginPrivate::onModeChanged(IMode *mode)
2260 {
2261      // FIXME: This one gets always called, even if switching between modes
2262      //        different then the debugger mode. E.g. Welcome and Help mode and
2263      //        also on shutdown.
2264
2265     m_mainWindow->onModeChanged(mode);
2266
2267     if (mode->id() != Constants::MODE_DEBUG)
2268         return;
2269
2270     EditorManager *editorManager = EditorManager::instance();
2271     if (editorManager->currentEditor())
2272         editorManager->currentEditor()->widget()->setFocus();
2273 }
2274
2275 void DebuggerPluginPrivate::showSettingsDialog()
2276 {
2277     ICore::instance()->showOptionsDialog(
2278         _(DEBUGGER_SETTINGS_CATEGORY),
2279         _(DEBUGGER_COMMON_SETTINGS_ID));
2280 }
2281
2282 void DebuggerPluginPrivate::dumpLog()
2283 {
2284     QString fileName = QFileDialog::getSaveFileName(mainWindow(),
2285         tr("Save Debugger Log"), QDir::tempPath());
2286     if (fileName.isEmpty())
2287         return;
2288     QFile file(fileName);
2289     if (!file.open(QIODevice::WriteOnly))
2290         return;
2291     QTextStream ts(&file);
2292     ts << m_logWindow->inputContents();
2293     ts << "\n\n=======================================\n\n";
2294     ts << m_logWindow->combinedContents();
2295 }
2296
2297 void DebuggerPluginPrivate::clearStatusMessage()
2298 {
2299     m_statusLabel->setText(m_lastPermanentStatusMessage);
2300 }
2301
2302 /*! Activates the previous mode when the current mode is the debug mode. */
2303 void DebuggerPluginPrivate::activatePreviousMode()
2304 {
2305     ModeManager *modeManager = ICore::instance()->modeManager();
2306
2307     if (modeManager->currentMode() == modeManager->mode(MODE_DEBUG)
2308             && !m_previousMode.isEmpty()) {
2309         modeManager->activateMode(m_previousMode);
2310         m_previousMode.clear();
2311     }
2312 }
2313
2314 void DebuggerPluginPrivate::activateDebugMode()
2315 {
2316     m_actions.reverseDirectionAction->setChecked(false);
2317     m_actions.reverseDirectionAction->setEnabled(false);
2318     ModeManager *modeManager = ModeManager::instance();
2319     m_previousMode = modeManager->currentMode()->id();
2320     modeManager->activateMode(_(MODE_DEBUG));
2321 }
2322
2323 void DebuggerPluginPrivate::sessionLoaded()
2324 {
2325     m_breakHandler->loadSessionData();
2326     dummyEngine()->watchHandler()->loadSessionData();
2327 }
2328
2329 void DebuggerPluginPrivate::aboutToUnloadSession()
2330 {
2331     m_breakHandler->removeSessionData();
2332     // Stop debugging the active project when switching sessions.
2333     // Note that at startup, session switches may occur, which interfere
2334     // with command-line debugging startup.
2335     // FIXME ABC: Still wanted? Iterate?
2336     //if (d->m_engine && state() != DebuggerNotReady
2337     //    && engine()->sp().startMode == StartInternal)
2338     //        d->m_engine->shutdown();
2339 }
2340
2341 void DebuggerPluginPrivate::aboutToSaveSession()
2342 {
2343     dummyEngine()->watchHandler()->loadSessionData();
2344     m_breakHandler->saveSessionData();
2345 }
2346
2347 void DebuggerPluginPrivate::executeDebuggerCommand()
2348 {
2349     if (QAction *action = qobject_cast<QAction *>(sender()))
2350         currentEngine()->executeDebuggerCommand(action->data().toString());
2351 }
2352
2353 void DebuggerPluginPrivate::showStatusMessage(const QString &msg0, int timeout)
2354 {
2355     showMessage(msg0, LogStatus);
2356     QString msg = msg0;
2357     msg.replace(QLatin1Char('\n'), QString());
2358     m_statusLabel->setText(msg);
2359     if (timeout > 0) {
2360         m_statusTimer.setSingleShot(true);
2361         m_statusTimer.start(timeout);
2362     } else {
2363         m_lastPermanentStatusMessage = msg;
2364         m_statusTimer.stop();
2365     }
2366 }
2367
2368 void DebuggerPluginPrivate::scriptExpressionEntered(const QString &expression)
2369 {
2370     currentEngine()->executeDebuggerCommand(expression);
2371 }
2372
2373 void DebuggerPluginPrivate::openMemoryEditor()
2374 {
2375     AddressDialog dialog;
2376     if (dialog.exec() == QDialog::Accepted)
2377         currentEngine()->openMemoryView(dialog.address());
2378 }
2379
2380 void DebuggerPluginPrivate::coreShutdown()
2381 {
2382     m_shuttingDown = true;
2383 }
2384
2385 const CPlusPlus::Snapshot &DebuggerPluginPrivate::cppCodeModelSnapshot() const
2386 {
2387     if (m_codeModelSnapshot.isEmpty() && action(UseCodeModel)->isChecked())
2388         m_codeModelSnapshot = CPlusPlus::CppModelManagerInterface::instance()->snapshot();
2389     return m_codeModelSnapshot;
2390 }
2391
2392 void DebuggerPluginPrivate::setSessionValue(const QString &name, const QVariant &value)
2393 {
2394     QTC_ASSERT(sessionManager(), return);
2395     sessionManager()->setValue(name, value);
2396     //qDebug() << "SET SESSION VALUE: " << name;
2397 }
2398
2399 QVariant DebuggerPluginPrivate::sessionValue(const QString &name)
2400 {
2401     QTC_ASSERT(sessionManager(), return QVariant());
2402     //qDebug() << "GET SESSION VALUE: " << name;
2403     return sessionManager()->value(name);
2404 }
2405
2406 void DebuggerPluginPrivate::openTextEditor(const QString &titlePattern0,
2407     const QString &contents)
2408 {
2409     if (m_shuttingDown)
2410         return;
2411     QString titlePattern = titlePattern0;
2412     EditorManager *editorManager = EditorManager::instance();
2413     QTC_ASSERT(editorManager, return);
2414     IEditor *editor = editorManager->openEditorWithContents(
2415         CC::K_DEFAULT_TEXT_EDITOR_ID, &titlePattern, contents);
2416     QTC_ASSERT(editor, return);
2417     editorManager->activateEditor(editor, EditorManager::IgnoreNavigationHistory);
2418 }
2419
2420
2421 void DebuggerPluginPrivate::clearCppCodeModelSnapshot()
2422 {
2423     m_codeModelSnapshot = CPlusPlus::Snapshot();
2424 }
2425
2426 void DebuggerPluginPrivate::showMessage(const QString &msg, int channel, int timeout)
2427 {
2428     //qDebug() << "PLUGIN OUTPUT: " << channel << msg;
2429     //ConsoleWindow *cw = m_consoleWindow;
2430     QTC_ASSERT(m_logWindow, return);
2431     switch (channel) {
2432         case StatusBar:
2433             // This will append to m_logWindow's output pane, too.
2434             showStatusMessage(msg, timeout);
2435             break;
2436         case LogMiscInput:
2437             m_logWindow->showInput(LogMisc, msg);
2438             m_logWindow->showOutput(LogMisc, msg);
2439             break;
2440         case LogInput:
2441             m_logWindow->showInput(LogInput, msg);
2442             m_logWindow->showOutput(LogInput, msg);
2443             break;
2444         case ScriptConsoleOutput:
2445             m_scriptConsoleWindow->appendResult(msg);
2446             break;
2447         case LogError: {
2448             m_logWindow->showOutput(channel, msg);
2449             QAction *action = m_mainWindow->dockWidget(_(DOCKWIDGET_OUTPUT))
2450                 ->toggleViewAction();
2451             if (!action->isChecked())
2452                 action->trigger();
2453             break;
2454         }
2455         default:
2456             m_logWindow->showOutput(channel, msg);
2457             break;
2458     }
2459 }
2460
2461 void DebuggerPluginPrivate::showQtDumperLibraryWarning(const QString &details)
2462 {
2463     QMessageBox dialog(mainWindow());
2464     QPushButton *qtPref = dialog.addButton(tr("Open Qt4 Options"),
2465         QMessageBox::ActionRole);
2466     QPushButton *helperOff = dialog.addButton(tr("Turn off Helper Usage"),
2467         QMessageBox::ActionRole);
2468     QPushButton *justContinue = dialog.addButton(tr("Continue Anyway"),
2469         QMessageBox::AcceptRole);
2470     dialog.setDefaultButton(justContinue);
2471     dialog.setWindowTitle(tr("Debugging Helper Missing"));
2472     dialog.setText(tr("The debugger could not load the debugging helper library."));
2473     dialog.setInformativeText(tr(
2474         "The debugging helper is used to nicely format the values of some Qt "
2475         "and Standard Library data types. "
2476         "It must be compiled for each used Qt version separately. "
2477         "On the Qt4 options page, select a Qt installation "
2478         "and click Rebuild."));
2479     if (!details.isEmpty())
2480         dialog.setDetailedText(details);
2481     dialog.exec();
2482     if (dialog.clickedButton() == qtPref) {
2483         ICore::instance()->showOptionsDialog(
2484             _(Qt4ProjectManager::Constants::QT_SETTINGS_CATEGORY),
2485             _(Qt4ProjectManager::Constants::QTVERSION_SETTINGS_PAGE_ID));
2486     } else if (dialog.clickedButton() == helperOff) {
2487         action(UseDebuggingHelpers)->setValue(qVariantFromValue(false), false);
2488     }
2489 }
2490
2491 void DebuggerPluginPrivate::createNewDock(QWidget *widget)
2492 {
2493     QDockWidget *dockWidget =
2494         m_mainWindow->createDockWidget(CppLanguage, widget);
2495     dockWidget->setWindowTitle(widget->windowTitle());
2496     dockWidget->setFeatures(QDockWidget::DockWidgetClosable);
2497     dockWidget->show();
2498 }
2499
2500 void DebuggerPluginPrivate::runControlStarted(DebuggerEngine *engine)
2501 {
2502     activateDebugMode();
2503     QString toolChainName =
2504         ToolChain::toolChainName(engine->startParameters().toolChainType);
2505     const QString message = tr("Starting debugger '%1' for tool chain '%2'...")
2506             .arg(engine->objectName()).arg(toolChainName);
2507     showMessage(message, StatusBar);
2508     showMessage(m_debuggerSettings->dump(), LogDebug);
2509     m_snapshotHandler->appendSnapshot(engine);
2510     connectEngine(engine);
2511 }
2512
2513 void DebuggerPluginPrivate::runControlFinished(DebuggerEngine *engine)
2514 {
2515     m_snapshotHandler->removeSnapshot(engine);
2516     if (m_snapshotHandler->size() == 0) {
2517         // Last engine quits.
2518         disconnectEngine();
2519         if (boolSetting(SwitchModeOnExit))
2520             activatePreviousMode();
2521     } else {
2522         // Connect to some existing engine.
2523         m_snapshotHandler->activateSnapshot(0);
2524     }
2525 }
2526
2527 void DebuggerPluginPrivate::remoteCommand(const QStringList &options,
2528     const QStringList &)
2529 {
2530     if (options.isEmpty())
2531         return;
2532
2533     unsigned enabledEngines = 0;
2534     QString errorMessage;
2535
2536     if (!parseArguments(options,
2537             &m_attachRemoteParameters, &enabledEngines, &errorMessage)) {
2538         qWarning("%s", qPrintable(errorMessage));
2539         return;
2540     }
2541
2542     if (!attachCmdLine())
2543         qWarning("%s", qPrintable(
2544             _("Incomplete remote attach command received: %1").
2545                arg(options.join(QString(QLatin1Char(' '))))));
2546 }
2547
2548 QString DebuggerPluginPrivate::gdbBinaryForToolChain(int toolChain) const
2549 {
2550     return GdbOptionsPage::gdbBinaryToolChainMap.key(toolChain);
2551 }
2552
2553 DebuggerLanguages DebuggerPluginPrivate::activeLanguages() const
2554 {
2555     QTC_ASSERT(m_mainWindow, return AnyLanguage);
2556     return m_mainWindow->activeDebugLanguages();
2557 }
2558
2559 bool DebuggerPluginPrivate::isReverseDebugging() const
2560 {
2561     return m_actions.reverseDirectionAction->isChecked();
2562 }
2563
2564 QMessageBox *showMessageBox(int icon, const QString &title,
2565     const QString &text, int buttons)
2566 {
2567     QMessageBox *mb = new QMessageBox(QMessageBox::Icon(icon),
2568         title, text, QMessageBox::StandardButtons(buttons),
2569         debuggerCore()->mainWindow());
2570     mb->setAttribute(Qt::WA_DeleteOnClose);
2571     mb->show();
2572     return mb;
2573 }
2574
2575 void DebuggerPluginPrivate::extensionsInitialized()
2576 {
2577     ICore *core = ICore::instance();
2578     QTC_ASSERT(core, return);
2579     m_coreSettings = core->settings();
2580     m_debuggerSettings = new DebuggerSettings(m_coreSettings);
2581
2582     m_continuableContext = Context("Gdb.Continuable");
2583     m_interruptibleContext = Context("Gdb.Interruptible");
2584     m_undisturbableContext = Context("Gdb.Undisturbable");
2585     m_finishedContext = Context("Gdb.Finished");
2586     m_anyContext.add(m_continuableContext);
2587     m_anyContext.add(m_interruptibleContext);
2588     m_anyContext.add(m_undisturbableContext);
2589     m_anyContext.add(m_finishedContext);
2590
2591     connect(core, SIGNAL(coreAboutToClose()), this, SLOT(coreShutdown()));
2592
2593     Core::ActionManager *am = core->actionManager();
2594     QTC_ASSERT(am, return);
2595
2596     const Context globalcontext(CC::C_GLOBAL);
2597     const Context cppDebuggercontext(C_CPPDEBUGGER);
2598     const Context qmlDebuggerContext(C_QMLDEBUGGER);
2599     const Context cppeditorcontext(CppEditor::Constants::C_CPPEDITOR);
2600
2601     m_startIcon = QIcon(_(":/debugger/images/debugger_start_small.png"));
2602     m_startIcon.addFile(__(":/debugger/images/debugger_start.png"));
2603     m_exitIcon = QIcon(_(":/debugger/images/debugger_stop_small.png"));
2604     m_exitIcon.addFile(__(":/debugger/images/debugger_stop.png"));
2605     m_continueIcon = QIcon(__(":/debugger/images/debugger_continue_small.png"));
2606     m_continueIcon.addFile(__(":/debugger/images/debugger_continue.png"));
2607     m_interruptIcon = QIcon(_(":/debugger/images/debugger_interrupt_small.png"));
2608     m_interruptIcon.addFile(__(":/debugger/images/debugger_interrupt.png"));
2609     m_locationMarkIcon = QIcon(_(":/debugger/images/location_16.png"));
2610
2611     m_busy = false;
2612
2613     m_statusLabel = new QLabel;
2614     m_statusLabel->setMinimumSize(QSize(30, 10));
2615
2616     m_breakHandler = new BreakHandler;
2617     m_breakWindow = new BreakWindow;
2618     m_breakWindow->setObjectName(DOCKWIDGET_BREAK);
2619     m_breakWindow->setModel(m_breakHandler->model());
2620
2621     //m_consoleWindow = new ConsoleWindow;
2622     //m_consoleWindow->setObjectName(QLatin1String("CppDebugConsole"));
2623     m_modulesWindow = new ModulesWindow;
2624     m_modulesWindow->setObjectName(DOCKWIDGET_MODULES);
2625     m_logWindow = new LogWindow;
2626     m_logWindow->setObjectName(DOCKWIDGET_OUTPUT);
2627     m_registerWindow = new RegisterWindow;
2628     m_registerWindow->setObjectName(DOCKWIDGET_REGISTER);
2629     m_stackWindow = new StackWindow;
2630     m_stackWindow->setObjectName(DOCKWIDGET_STACK);
2631     m_sourceFilesWindow = new SourceFilesWindow;
2632     m_sourceFilesWindow->setObjectName(DOCKWIDGET_SOURCE_FILES);
2633     m_threadsWindow = new ThreadsWindow;
2634     m_threadsWindow->setObjectName(DOCKWIDGET_THREADS);
2635     m_returnWindow = new WatchWindow(WatchWindow::ReturnType);
2636     m_returnWindow->setObjectName(QLatin1String("CppDebugReturn"));
2637     m_localsWindow = new WatchWindow(WatchWindow::LocalsType);
2638     m_localsWindow->setObjectName(QLatin1String("CppDebugLocals"));
2639     m_watchersWindow = new WatchWindow(WatchWindow::WatchersType);
2640     m_watchersWindow->setObjectName(QLatin1String("CppDebugWatchers"));
2641     m_scriptConsoleWindow = new ScriptConsole;
2642     m_scriptConsoleWindow->setWindowTitle(tr("QML Script Console"));
2643     m_scriptConsoleWindow->setObjectName(DOCKWIDGET_QML_SCRIPTCONSOLE);
2644     connect(m_scriptConsoleWindow, SIGNAL(expressionEntered(QString)),
2645         SLOT(scriptExpressionEntered(QString)));
2646
2647     // Snapshot
2648     m_snapshotHandler = new SnapshotHandler;
2649     m_snapshotWindow = new SnapshotWindow(m_snapshotHandler);
2650     m_snapshotWindow->setObjectName(DOCKWIDGET_SNAPSHOTS);
2651     m_snapshotWindow->setModel(m_snapshotHandler->model());
2652
2653     // Watchers
2654     connect(m_localsWindow->header(), SIGNAL(sectionResized(int,int,int)),
2655         SLOT(updateWatchersHeader(int,int,int)), Qt::QueuedConnection);
2656
2657     QAction *act = 0;
2658
2659     act = m_actions.continueAction = new QAction(tr("Continue"), this);
2660     act->setIcon(m_continueIcon);
2661     connect(act, SIGNAL(triggered()), SLOT(handleExecContinue()));
2662
2663     act = m_actions.exitAction = new QAction(tr("Exit Debugger"), this);
2664     act->setIcon(m_exitIcon);
2665     connect(act, SIGNAL(triggered()), SLOT(handleExecExit()));
2666
2667     act = m_actions.interruptAction = new QAction(tr("Interrupt"), this);
2668     act->setIcon(m_interruptIcon);
2669     connect(act, SIGNAL(triggered()), SLOT(handleExecInterrupt()));
2670
2671     // A "disabled pause" seems to be a good choice.
2672     act = m_actions.undisturbableAction = new QAction(tr("Debugger is Busy"), this);
2673     act->setIcon(m_interruptIcon);
2674     act->setEnabled(false);
2675
2676     act = m_actions.resetAction = new QAction(tr("Abort Debugging"), this);
2677     act->setToolTip(tr("Aborts debugging and "
2678         "resets the debugger to the initial state."));
2679     connect(act, SIGNAL(triggered()), SLOT(handleExecReset()));
2680
2681     act = m_actions.nextAction = new QAction(tr("Step Over"), this);
2682     act->setIcon(QIcon(__(":/debugger/images/debugger_stepover_small.png")));
2683     connect(act, SIGNAL(triggered()), SLOT(handleExecNext()));
2684
2685     act = m_actions.stepAction = new QAction(tr("Step Into"), this);
2686     act->setIcon(QIcon(__(":/debugger/images/debugger_stepinto_small.png")));
2687     connect(act, SIGNAL(triggered()), SLOT(handleExecStep()));
2688
2689     act = m_actions.stepOutAction = new QAction(tr("Step Out"), this);
2690     act->setIcon(QIcon(__(":/debugger/images/debugger_stepout_small.png")));
2691     connect(act, SIGNAL(triggered()), SLOT(handleExecStepOut()));
2692
2693     act = m_actions.runToLineAction = new QAction(tr("Run to Line"), this);
2694     connect(act, SIGNAL(triggered()), SLOT(handleExecRunToLine()));
2695
2696     act = m_actions.runToFunctionAction =
2697         new QAction(tr("Run to Outermost Function"), this);
2698     connect(act, SIGNAL(triggered()), SLOT(handleExecRunToFunction()));
2699
2700     act = m_actions.returnFromFunctionAction =
2701         new QAction(tr("Immediately Return From Inner Function"), this);
2702     connect(act, SIGNAL(triggered()), SLOT(handleExecReturn()));
2703
2704     act = m_actions.jumpToLineAction = new QAction(tr("Jump to Line"), this);
2705     connect(act, SIGNAL(triggered()), SLOT(handleExecJumpToLine()));
2706
2707     act = m_actions.breakAction = new QAction(tr("Toggle Breakpoint"), this);
2708
2709     act = m_actions.watchAction1 = new QAction(tr("Add to Watch Window"), this);
2710     connect(act, SIGNAL(triggered()), SLOT(handleAddToWatchWindow()));
2711
2712     act = m_actions.watchAction2 = new QAction(tr("Add to Watch Window"), this);
2713     connect(act, SIGNAL(triggered()), SLOT(handleAddToWatchWindow()));
2714
2715     //m_actions.snapshotAction = new QAction(tr("Create Snapshot"), this);
2716     //m_actions.snapshotAction->setProperty(Role, RequestCreateSnapshotRole);
2717     //m_actions.snapshotAction->setIcon(
2718     //    QIcon(__(":/debugger/images/debugger_snapshot_small.png")));
2719
2720     act = m_actions.reverseDirectionAction =
2721         new QAction(tr("Reverse Direction"), this);
2722     act->setCheckable(true);
2723     act->setChecked(false);
2724     act->setCheckable(false);
2725     act->setIcon(QIcon(__(":/debugger/images/debugger_reversemode_16.png")));
2726     act->setIconVisibleInMenu(false);
2727
2728     act = m_actions.frameDownAction = new QAction(tr("Move to Called Frame"), this);
2729     connect(act, SIGNAL(triggered()), SLOT(handleFrameDown()));
2730
2731     act = m_actions.frameUpAction = new QAction(tr("Move to Calling Frame"), this);
2732     connect(act, SIGNAL(triggered()), SLOT(handleFrameUp()));
2733
2734     connect(action(OperateByInstruction), SIGNAL(triggered(bool)),
2735         SLOT(handleOperateByInstructionTriggered(bool)));
2736
2737     connect(&m_statusTimer, SIGNAL(timeout()), SLOT(clearStatusMessage()));
2738
2739     connect(action(ExecuteCommand), SIGNAL(triggered()),
2740         SLOT(executeDebuggerCommand()));
2741
2742     ActionContainer *debugMenu =
2743         am->actionContainer(ProjectExplorer::Constants::M_DEBUG);
2744
2745     // Dock widgets
2746     QDockWidget *dock = 0;
2747     dock = m_mainWindow->createDockWidget(CppLanguage, m_modulesWindow);
2748     connect(dock->toggleViewAction(), SIGNAL(toggled(bool)),
2749         SLOT(modulesDockToggled(bool)), Qt::QueuedConnection);
2750
2751     dock = m_mainWindow->createDockWidget(CppLanguage, m_registerWindow);
2752     connect(dock->toggleViewAction(), SIGNAL(toggled(bool)),
2753         SLOT(registerDockToggled(bool)), Qt::QueuedConnection);
2754
2755     dock = m_mainWindow->createDockWidget(CppLanguage, m_sourceFilesWindow);
2756     connect(dock->toggleViewAction(), SIGNAL(toggled(bool)),
2757         SLOT(sourceFilesDockToggled(bool)), Qt::QueuedConnection);
2758
2759     dock = m_mainWindow->createDockWidget(AnyLanguage, m_logWindow);
2760     dock->setProperty(DOCKWIDGET_DEFAULT_AREA, Qt::TopDockWidgetArea);
2761
2762     m_mainWindow->createDockWidget(CppLanguage, m_breakWindow);
2763     //m_mainWindow->createDockWidget(CppLanguage, m_consoleWindow);
2764     m_mainWindow->createDockWidget(CppLanguage, m_snapshotWindow);
2765     m_mainWindow->createDockWidget(CppLanguage, m_stackWindow);
2766     m_mainWindow->createDockWidget(CppLanguage, m_threadsWindow);
2767     m_mainWindow->createDockWidget(QmlLanguage, m_scriptConsoleWindow);
2768
2769     QSplitter *localsAndWatchers = new Core::MiniSplitter(Qt::Vertical);
2770     localsAndWatchers->setObjectName(DOCKWIDGET_WATCHERS);
2771     localsAndWatchers->setWindowTitle(m_localsWindow->windowTitle());
2772     localsAndWatchers->addWidget(m_localsWindow);
2773     localsAndWatchers->addWidget(m_returnWindow);
2774     localsAndWatchers->addWidget(m_watchersWindow);
2775     localsAndWatchers->setStretchFactor(0, 3);
2776     localsAndWatchers->setStretchFactor(1, 1);
2777     localsAndWatchers->setStretchFactor(2, 1);
2778
2779     dock = m_mainWindow->createDockWidget(CppLanguage, localsAndWatchers);
2780     dock->setProperty(DOCKWIDGET_DEFAULT_AREA, Qt::RightDockWidgetArea);
2781
2782     m_debuggerSettings->readSettings();
2783     GdbOptionsPage::readGdbBinarySettings();
2784
2785     // Register factory of DebuggerRunControl.
2786     m_debuggerRunControlFactory = new DebuggerRunControlFactory
2787         (m_plugin, DebuggerEngineType(m_cmdLineEnabledEngines));
2788     m_plugin->addAutoReleasedObject(m_debuggerRunControlFactory);
2789
2790     // The main "Start Debugging" action.
2791     act = m_debugAction = new QAction(this);
2792     QIcon debuggerIcon(":/projectexplorer/images/debugger_start_small.png");
2793     debuggerIcon.addFile(":/projectexplorer/images/debugger_start.png");
2794     act->setIcon(debuggerIcon);
2795     act->setText(tr("Start Debugging"));
2796     connect(act, SIGNAL(triggered()), this, SLOT(debugProject()));
2797
2798     // Handling of external applications.
2799     act = m_startExternalAction = new QAction(this);
2800     act->setText(tr("Start and Debug External Application..."));
2801     connect(act, SIGNAL(triggered()), SLOT(startExternalApplication()));
2802
2803     act = m_startRemoteLldbAction = new QAction(this);
2804     act->setText(tr("Start and Debug External Application with External Engine..."));
2805     connect(act, SIGNAL(triggered()), SLOT(startRemoteEngine()));
2806
2807     act = m_attachExternalAction = new QAction(this);
2808     act->setText(tr("Attach to Running External Application..."));
2809     connect(act, SIGNAL(triggered()), SLOT(attachExternalApplication()));
2810
2811     act = m_attachCoreAction = new QAction(this);
2812     act->setText(tr("Attach to Core..."));
2813     connect(act, SIGNAL(triggered()), SLOT(attachCore()));
2814
2815     act = m_attachTcfAction = new QAction(this);
2816     act->setText(tr("Attach to Running Tcf Agent..."));
2817     act->setToolTip(tr("This attaches to a running "
2818         "'Target Communication Framework' agent."));
2819     connect(act, SIGNAL(triggered()), SLOT(attachRemoteTcf()));
2820
2821     act = m_startRemoteAction = new QAction(this);
2822     act->setText(tr("Start and Attach to Remote Application..."));
2823     connect(act, SIGNAL(triggered()), SLOT(startRemoteApplication()));
2824
2825 #ifdef Q_OS_WIN
2826     m_startRemoteCdbAction = new QAction(tr("Attach to Remote CDB Session..."), this);
2827     connect(m_startRemoteCdbAction, SIGNAL(triggered()), SLOT(startRemoteCdbSession()));
2828 #endif
2829
2830     act = m_detachAction = new QAction(this);
2831     act->setText(tr("Detach Debugger"));
2832     connect(act, SIGNAL(triggered()), SLOT(handleExecDetach()));
2833
2834     Command *cmd = 0;
2835     ActionContainer *mstart = am->actionContainer(PE::M_DEBUG_STARTDEBUGGING);
2836
2837     cmd = am->registerAction(m_debugAction, Constants::DEBUG, globalcontext);
2838     cmd->setAttribute(Core::Command::CA_UpdateText);
2839     cmd->setAttribute(Core::Command::CA_UpdateIcon);
2840     cmd->setDefaultText(tr("Start Debugging"));
2841     cmd->setDefaultKeySequence(QKeySequence(Constants::DEBUG_KEY));
2842     mstart->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
2843     Core::ICore::instance()->modeManager()->addAction(cmd, Constants::P_ACTION_DEBUG);
2844
2845     cmd = am->registerAction(m_actions.continueAction,
2846         Constants::DEBUG, m_continuableContext);
2847     mstart->addAction(cmd, CC::G_DEFAULT_ONE);
2848
2849     cmd = am->registerAction(m_startExternalAction,
2850         Constants::STARTEXTERNAL, globalcontext);
2851     cmd->setAttribute(Command::CA_Hide);
2852     mstart->addAction(cmd, CC::G_DEFAULT_ONE);
2853
2854     cmd = am->registerAction(m_startRemoteLldbAction,
2855         Constants::STARTREMOTELLDB, globalcontext);
2856     cmd->setAttribute(Command::CA_Hide);
2857     mstart->addAction(cmd, CC::G_DEFAULT_ONE);
2858
2859     cmd = am->registerAction(m_attachExternalAction,
2860         Constants::ATTACHEXTERNAL, globalcontext);
2861     cmd->setAttribute(Command::CA_Hide);
2862     mstart->addAction(cmd, CC::G_DEFAULT_ONE);
2863
2864     cmd = am->registerAction(m_attachCoreAction,
2865         Constants::ATTACHCORE, globalcontext);
2866
2867     cmd->setAttribute(Command::CA_Hide);
2868     mstart->addAction(cmd, CC::G_DEFAULT_ONE);
2869
2870     cmd = am->registerAction(m_attachTcfAction,
2871         Constants::ATTACHTCF, globalcontext);
2872     mstart->addAction(cmd, CC::G_DEFAULT_ONE);
2873
2874     cmd = am->registerAction(m_startRemoteAction,
2875         Constants::ATTACHREMOTE, globalcontext);
2876     cmd->setAttribute(Command::CA_Hide);
2877     mstart->addAction(cmd, CC::G_DEFAULT_ONE);
2878
2879     if (m_startRemoteCdbAction) {
2880         cmd = am->registerAction(m_startRemoteCdbAction,
2881                                  Constants::ATTACHREMOTECDB, globalcontext);
2882         cmd->setAttribute(Command::CA_Hide);
2883         mstart->addAction(cmd, CC::G_DEFAULT_ONE);
2884     }
2885
2886     cmd = am->registerAction(m_detachAction,
2887         Constants::DETACH, globalcontext);
2888     cmd->setAttribute(Command::CA_Hide);
2889     debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
2890
2891     cmd = am->registerAction(m_actions.exitAction,
2892         Constants::STOP, globalcontext);
2893     //cmd->setDefaultKeySequence(QKeySequence(Constants::STOP_KEY));
2894     cmd->setDefaultText(tr("Stop Debugger"));
2895     debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
2896
2897     cmd = am->registerAction(m_actions.interruptAction,
2898         Constants::DEBUG, m_interruptibleContext);
2899     cmd->setDefaultText(tr("Interrupt Debugger"));
2900
2901     cmd = am->registerAction(m_actions.undisturbableAction,
2902         Constants::DEBUG, m_undisturbableContext);
2903     cmd->setDefaultText(tr("Debugger is Busy"));
2904
2905     cmd = am->registerAction(m_actions.resetAction,
2906         Constants::RESET, globalcontext);
2907     //cmd->setDefaultKeySequence(QKeySequence(Constants::RESET_KEY));
2908     cmd->setDefaultText(tr("Reset Debugger"));
2909     debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
2910
2911     QAction *sep = new QAction(this);
2912     sep->setSeparator(true);
2913     cmd = am->registerAction(sep, _("Debugger.Sep.Step"), globalcontext);
2914     debugMenu->addAction(cmd);
2915
2916     cmd = am->registerAction(m_actions.nextAction,
2917         Constants::NEXT, cppDebuggercontext);
2918     cmd->setDefaultKeySequence(QKeySequence(Constants::NEXT_KEY));
2919     cmd->setAttribute(Command::CA_Hide);
2920     debugMenu->addAction(cmd);
2921
2922     cmd = am->registerAction(m_actions.stepAction,
2923         Constants::STEP, cppDebuggercontext);
2924     cmd->setDefaultKeySequence(QKeySequence(Constants::STEP_KEY));
2925     cmd->setAttribute(Command::CA_Hide);
2926     debugMenu->addAction(cmd);
2927
2928     cmd = am->registerAction(m_actions.stepOutAction,
2929         Constants::STEPOUT, cppDebuggercontext);
2930     cmd->setDefaultKeySequence(QKeySequence(Constants::STEPOUT_KEY));
2931     cmd->setAttribute(Command::CA_Hide);
2932     debugMenu->addAction(cmd);
2933
2934     cmd = am->registerAction(m_actions.runToLineAction,
2935         Constants::RUN_TO_LINE1, cppDebuggercontext);
2936     cmd->setDefaultKeySequence(QKeySequence(Constants::RUN_TO_LINE_KEY));
2937     cmd->setAttribute(Command::CA_Hide);
2938     debugMenu->addAction(cmd);
2939
2940     cmd = am->registerAction(m_actions.runToFunctionAction,
2941         Constants::RUN_TO_FUNCTION, cppDebuggercontext);
2942     cmd->setDefaultKeySequence(QKeySequence(Constants::RUN_TO_FUNCTION_KEY));
2943     cmd->setAttribute(Command::CA_Hide);
2944     debugMenu->addAction(cmd);
2945
2946     cmd = am->registerAction(m_actions.jumpToLineAction,
2947         Constants::JUMP_TO_LINE1, cppDebuggercontext);
2948     cmd->setAttribute(Command::CA_Hide);
2949     debugMenu->addAction(cmd);
2950
2951     cmd = am->registerAction(m_actions.returnFromFunctionAction,
2952         Constants::RETURN_FROM_FUNCTION, cppDebuggercontext);
2953     cmd->setAttribute(Command::CA_Hide);
2954     debugMenu->addAction(cmd);
2955
2956     cmd = am->registerAction(m_actions.reverseDirectionAction,
2957         Constants::REVERSE, cppDebuggercontext);
2958     cmd->setDefaultKeySequence(QKeySequence(Constants::REVERSE_KEY));
2959     cmd->setAttribute(Command::CA_Hide);
2960     debugMenu->addAction(cmd);
2961
2962     sep = new QAction(this);
2963     sep->setSeparator(true);
2964     cmd = am->registerAction(sep, _("Debugger.Sep.Break"), globalcontext);
2965     debugMenu->addAction(cmd);
2966
2967     //cmd = am->registerAction(m_actions.snapshotAction,
2968     //    Constants::SNAPSHOT, cppDebuggercontext);
2969     //cmd->setDefaultKeySequence(QKeySequence(Constants::SNAPSHOT_KEY));
2970     //cmd->setAttribute(Command::CA_Hide);
2971     //debugMenu->addAction(cmd);
2972
2973     cmd = am->registerAction(m_actions.frameDownAction,
2974         Constants::FRAME_DOWN, cppDebuggercontext);
2975     cmd = am->registerAction(m_actions.frameUpAction,
2976         Constants::FRAME_UP, cppDebuggercontext);
2977
2978     cmd = am->registerAction(action(OperateByInstruction),
2979         Constants::OPERATE_BY_INSTRUCTION, cppDebuggercontext);
2980     cmd->setAttribute(Command::CA_Hide);
2981     debugMenu->addAction(cmd);
2982
2983     cmd = am->registerAction(m_actions.breakAction,
2984         Constants::TOGGLE_BREAK, globalcontext);
2985     cmd->setDefaultKeySequence(QKeySequence(Constants::TOGGLE_BREAK_KEY));
2986     debugMenu->addAction(cmd);
2987     connect(m_actions.breakAction, SIGNAL(triggered()),
2988         SLOT(toggleBreakpoint()));
2989
2990     sep = new QAction(this);
2991     sep->setSeparator(true);
2992     cmd = am->registerAction(sep, _("Debugger.Sep.Watch"), globalcontext);
2993     debugMenu->addAction(cmd);
2994
2995     cmd = am->registerAction(m_actions.watchAction1,
2996         Constants::ADD_TO_WATCH1, cppeditorcontext);
2997     cmd->action()->setEnabled(true);
2998     //cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+D,Ctrl+W")));
2999     debugMenu->addAction(cmd);
3000
3001     // If the CppEditor plugin is there, we want to add something to
3002     // the editor context menu.
3003     if (ActionContainer *editorContextMenu =
3004             am->actionContainer(CppEditor::Constants::M_CONTEXT)) {
3005         cmd = am->registerAction(sep, _("Debugger.Sep.Views"),
3006             cppDebuggercontext);
3007         editorContextMenu->addAction(cmd);
3008         cmd->setAttribute(Command::CA_Hide);
3009
3010         cmd = am->registerAction(m_actions.watchAction2,
3011             Constants::ADD_TO_WATCH2, cppDebuggercontext);
3012         cmd->action()->setEnabled(true);
3013         editorContextMenu->addAction(cmd);
3014         cmd->setAttribute(Command::CA_Hide);
3015     }
3016
3017     m_plugin->addAutoReleasedObject(new CommonOptionsPage);
3018     QList<Core::IOptionsPage *> engineOptionPages;
3019     if (m_cmdLineEnabledEngines & GdbEngineType)
3020         addGdbOptionPages(&engineOptionPages);
3021 #ifdef Q_OS_WIN
3022    addCdb2OptionPages(&engineOptionPages);
3023 #endif
3024 #ifdef WITH_LLDB
3025     if (m_cmdLineEnabledEngines & LldbEngineType)
3026         addLldbOptionPages(&engineOptionPages);
3027 #endif
3028
3029     //if (m_cmdLineEnabledEngines & ScriptEngineType)
3030     //    addScriptOptionPages(&engineOptionPages);
3031     //if (m_cmdLineEnabledEngines & TcfEngineType)
3032     //    addTcfOptionPages(&engineOptionPages);
3033     foreach (Core::IOptionsPage *op, engineOptionPages)
3034         m_plugin->addAutoReleasedObject(op);
3035     m_plugin->addAutoReleasedObject(new DebuggingHelperOptionPage);
3036
3037     connect(ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*)),
3038         SLOT(onModeChanged(Core::IMode*)));
3039
3040
3041     // Debug mode setup
3042     m_plugin->addAutoReleasedObject(new DebugMode);
3043
3044     //
3045     //  Connections
3046     //
3047
3048     // TextEditor
3049     connect(TextEditorSettings::instance(),
3050         SIGNAL(fontSettingsChanged(TextEditor::FontSettings)),
3051         SLOT(fontSettingsChanged(TextEditor::FontSettings)));
3052
3053     // ProjectExplorer
3054     connect(sessionManager(), SIGNAL(sessionLoaded()),
3055         SLOT(sessionLoaded()));
3056     connect(sessionManager(), SIGNAL(aboutToSaveSession()),
3057         SLOT(aboutToSaveSession()));
3058     connect(sessionManager(), SIGNAL(aboutToUnloadSession()),
3059         SLOT(aboutToUnloadSession()));
3060     connect(ProjectExplorerPlugin::instance(), SIGNAL(updateRunActions()),
3061         SLOT(updateDebugActions()));
3062
3063     // EditorManager
3064     QObject *editorManager = core->editorManager();
3065     connect(editorManager, SIGNAL(editorOpened(Core::IEditor*)),
3066         SLOT(editorOpened(Core::IEditor*)));
3067
3068     // Application interaction
3069     connect(action(SettingsDialog), SIGNAL(triggered()),
3070         SLOT(showSettingsDialog()));
3071
3072     // Toolbar
3073     QWidget *toolbarContainer = new QWidget;
3074
3075     QHBoxLayout *hbox = new QHBoxLayout(toolbarContainer);
3076     hbox->setMargin(0);
3077     hbox->setSpacing(0);
3078     hbox->addWidget(toolButton(am->command(Constants::DEBUG)->action()));
3079     hbox->addWidget(toolButton(am->command(STOP)->action()));
3080     hbox->addWidget(toolButton(am->command(NEXT)->action()));
3081     hbox->addWidget(toolButton(am->command(STEP)->action()));
3082     hbox->addWidget(toolButton(am->command(STEPOUT)->action()));
3083     hbox->addWidget(toolButton(am->command(OPERATE_BY_INSTRUCTION)->action()));
3084
3085     //hbox->addWidget(new Utils::StyledSeparator);
3086     m_reverseToolButton = toolButton(am->command(REVERSE)->action());
3087     hbox->addWidget(m_reverseToolButton);
3088     //m_reverseToolButton->hide();
3089
3090     hbox->addWidget(new Utils::StyledSeparator);
3091     hbox->addWidget(new QLabel(tr("Threads:")));
3092
3093     m_threadBox = new QComboBox;
3094     connect(m_threadBox, SIGNAL(activated(int)), SLOT(selectThread(int)));
3095
3096     hbox->addWidget(m_threadBox);
3097     hbox->addSpacerItem(new QSpacerItem(4, 0));
3098     hbox->addWidget(m_statusLabel, 10);
3099
3100     m_mainWindow->setToolbar(CppLanguage, toolbarContainer);
3101
3102     connect(action(EnableReverseDebugging),
3103         SIGNAL(valueChanged(QVariant)),
3104         SLOT(enableReverseDebuggingTriggered(QVariant)));
3105
3106     setInitialState();
3107     connectEngine(0);
3108
3109     connect(sessionManager(),
3110         SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
3111         SLOT(onCurrentProjectChanged(ProjectExplorer::Project*)));
3112
3113     QTC_ASSERT(m_coreSettings, /**/);
3114     m_watchersWindow->setVisible(false);
3115     m_returnWindow->setVisible(false);
3116
3117     // time gdb -i mi -ex 'debuggerplugin.cpp:800' -ex r -ex q bin/qtcreator.bin
3118     const QByteArray env = qgetenv("QTC_DEBUGGER_TEST");
3119     //qDebug() << "EXTENSIONS INITIALIZED:" << env;
3120     // if (!env.isEmpty())
3121     //    m_plugin->runTest(QString::fromLocal8Bit(env));
3122     if (m_attachRemoteParameters.attachPid
3123             || !m_attachRemoteParameters.attachTarget.isEmpty())
3124         QTimer::singleShot(0, this, SLOT(attachCmdLine()));
3125 }
3126
3127 Utils::SavedAction *DebuggerPluginPrivate::action(int code) const
3128 {
3129     return m_debuggerSettings->item(code);
3130 }
3131
3132 bool DebuggerPluginPrivate::boolSetting(int code) const
3133 {
3134     return m_debuggerSettings->item(code)->value().toBool();
3135 }
3136
3137 QString DebuggerPluginPrivate::stringSetting(int code) const
3138 {
3139     return m_debuggerSettings->item(code)->value().toString();
3140 }
3141
3142 void DebuggerPluginPrivate::showModuleSymbols(const QString &moduleName,
3143     const Symbols &symbols)
3144 {
3145     QTreeWidget *w = new QTreeWidget;
3146     w->setColumnCount(5);
3147     w->setRootIsDecorated(false);
3148     w->setAlternatingRowColors(true);
3149     w->setSortingEnabled(true);
3150     w->setObjectName("Symbols." + moduleName);
3151     QStringList header;
3152     header.append(tr("Symbol"));
3153     header.append(tr("Address"));
3154     header.append(tr("Code"));
3155     header.append(tr("Section"));
3156     header.append(tr("Name"));
3157     w->setHeaderLabels(header);
3158     w->setWindowTitle(tr("Symbols in \"%1\"").arg(moduleName));
3159     foreach (const Symbol &s, symbols) {
3160         QTreeWidgetItem *it = new QTreeWidgetItem;
3161         it->setData(0, Qt::DisplayRole, s.name);
3162         it->setData(1, Qt::DisplayRole, s.address);
3163         it->setData(2, Qt::DisplayRole, s.state);
3164         it->setData(3, Qt::DisplayRole, s.section);
3165         it->setData(4, Qt::DisplayRole, s.demangled);
3166         w->addTopLevelItem(it);
3167     }
3168     createNewDock(w);
3169 }
3170
3171 void DebuggerPluginPrivate::aboutToShutdown()
3172 {
3173     disconnect(sessionManager(),
3174         SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
3175         this, 0);
3176     m_debuggerSettings->writeSettings();
3177     m_mainWindow->writeSettings();
3178     if (GdbOptionsPage::gdbBinariesChanged)
3179         GdbOptionsPage::writeGdbBinarySettings();
3180 }
3181
3182 } // namespace Internal
3183
3184
3185 ///////////////////////////////////////////////////////////////////////
3186 //
3187 // DebuggerPlugin
3188 //
3189 ///////////////////////////////////////////////////////////////////////
3190
3191 using namespace Debugger::Internal;
3192
3193 DebuggerPlugin::DebuggerPlugin()
3194 {
3195     theDebuggerCore = new DebuggerPluginPrivate(this);
3196 }
3197
3198 DebuggerPlugin::~DebuggerPlugin()
3199 {
3200     delete theDebuggerCore;
3201     theDebuggerCore = 0;
3202 }
3203
3204 bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMessage)
3205 {
3206     return theDebuggerCore->initialize(arguments, errorMessage);
3207 }
3208
3209 ExtensionSystem::IPlugin::ShutdownFlag DebuggerPlugin::aboutToShutdown()
3210 {
3211     theDebuggerCore->aboutToShutdown();
3212     return SynchronousShutdown;
3213 }
3214
3215 void DebuggerPlugin::remoteCommand(const QStringList &options,
3216     const QStringList &list)
3217 {
3218     theDebuggerCore->remoteCommand(options, list);
3219 }
3220
3221
3222 DebuggerRunControl *DebuggerPlugin::createDebugger
3223     (const DebuggerStartParameters &sp, RunConfiguration *rc)
3224 {
3225     return theDebuggerCore->createDebugger(sp, rc);
3226 }
3227
3228 void DebuggerPlugin::startDebugger(RunControl *runControl)
3229 {
3230     theDebuggerCore->startDebugger(runControl);
3231 }
3232
3233 void DebuggerPlugin::extensionsInitialized()
3234 {
3235     theDebuggerCore->extensionsInitialized();
3236 }
3237
3238 bool DebuggerPlugin::isActiveDebugLanguage(int language)
3239 {
3240     return theDebuggerCore->isActiveDebugLanguage(language);
3241 }
3242
3243 DebuggerMainWindow *DebuggerPlugin::mainWindow()
3244 {
3245     return theDebuggerCore->m_mainWindow;
3246 }
3247
3248 QWidget *DebugMode::widget()
3249 {
3250     if (!m_widget) {
3251         //qDebug() << "CREATING DEBUG MODE WIDGET";
3252         m_widget = theDebuggerCore->m_mainWindow->createContents(this);
3253         m_widget->setFocusProxy(EditorManager::instance());
3254     }
3255     return m_widget;
3256 }
3257
3258 //////////////////////////////////////////////////////////////////////
3259 //
3260 // Testing
3261 //
3262 //////////////////////////////////////////////////////////////////////
3263
3264 /*
3265 void DebuggerPlugin::runTest(const QString &fileName)
3266 {
3267     DebuggerStartParameters sp;
3268     sp.executable = fileName;
3269     sp.processArgs = QStringList() << "--run-debuggee";
3270     sp.workingDirectory.clear();
3271     startDebugger(m_debuggerRunControlFactory->create(sp));
3272 }
3273 */
3274
3275 } // namespace Debugger
3276
3277 #include "debuggerplugin.moc"
3278
3279 Q_EXPORT_PLUGIN(Debugger::DebuggerPlugin)