debuggermanager.cpp 63.6 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2
3
4
**
** This file is part of Qt Creator
**
hjk's avatar
hjk committed
5
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
con's avatar
con committed
6
**
7
** Contact: Nokia Corporation (qt-info@nokia.com)
con's avatar
con committed
8
**
9
** Commercial Usage
10
**
11
12
13
14
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
15
**
16
** GNU Lesser General Public License Usage
17
**
18
19
20
21
22
23
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24
**
25
** If you are unsure which license is appropriate for your use, please
hjk's avatar
hjk committed
26
** contact the sales department at http://qt.nokia.com/contact.
con's avatar
con committed
27
**
28
**************************************************************************/
con's avatar
con committed
29
30
31

#include "debuggermanager.h"

32
#include "debuggerplugin.h"
33
#include "debuggeractions.h"
34
#include "debuggeragents.h"
35
#include "debuggerrunner.h"
con's avatar
con committed
36
37
#include "debuggerconstants.h"
#include "idebuggerengine.h"
38
#include "debuggerstringutils.h"
39
#include "watchutils.h"
40
41
#include "debuggeruiswitcher.h"
#include "debuggermainwindow.h"
con's avatar
con committed
42
43
44
45
46

#include "breakwindow.h"
#include "debuggeroutputwindow.h"
#include "moduleswindow.h"
#include "registerwindow.h"
47
#include "snapshotwindow.h"
con's avatar
con committed
48
#include "stackwindow.h"
49
#include "sourcefileswindow.h"
con's avatar
con committed
50
51
52
53
54
55
#include "threadswindow.h"
#include "watchwindow.h"

#include "breakhandler.h"
#include "moduleshandler.h"
#include "registerhandler.h"
56
#include "snapshothandler.h"
con's avatar
con committed
57
#include "stackhandler.h"
58
#include "stackframe.h"
con's avatar
con committed
59
60
#include "watchhandler.h"

61
#include "debuggerdialogs.h"
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
62
#ifdef Q_OS_WIN
63
#  include "shared/peutils.h"
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
64
#endif
65

66
#include <coreplugin/icore.h>
67
#include <coreplugin/minisplitter.h>
68
#include <coreplugin/editormanager/editormanager.h>
69
#include <utils/qtcassert.h>
70
#include <utils/savedaction.h>
71
#include <projectexplorer/toolchain.h>
72
73
#include <cplusplus/CppDocument.h>
#include <cpptools/cppmodelmanagerinterface.h>
74
#include <qt4projectmanager/qt4projectmanagerconstants.h>
75
#include <texteditor/fontsettings.h>
76
#include <texteditor/itexteditor.h>
77

con's avatar
con committed
78
79
80
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
81
#include <QtCore/QTextStream>
con's avatar
con committed
82
#include <QtCore/QTime>
83
#include <QtCore/QTimer>
con's avatar
con committed
84

85
#include <QtGui/QApplication>
con's avatar
con committed
86
87
88
89
90
91
92
93
#include <QtGui/QAction>
#include <QtGui/QComboBox>
#include <QtGui/QDockWidget>
#include <QtGui/QErrorMessage>
#include <QtGui/QFileDialog>
#include <QtGui/QLabel>
#include <QtGui/QMessageBox>
#include <QtGui/QPlainTextEdit>
94
#include <QtGui/QPushButton>
con's avatar
con committed
95
96
97
98
99
100
#include <QtGui/QStatusBar>
#include <QtGui/QTextBlock>
#include <QtGui/QTextCursor>
#include <QtGui/QToolButton>
#include <QtGui/QToolTip>

101
102
103
104
#define DEBUG_STATE 1
#ifdef DEBUG_STATE
// use  Q_FUNC_INFO?
#   define STATE_DEBUG(s) \
hjk's avatar
hjk committed
105
106
    do { QString msg; QTextStream ts(&msg); ts << s; \
      showDebuggerOutput(LogDebug, msg); } while (0)
107
108
109
110
#else
#   define STATE_DEBUG(s)
#endif

111
112
// Note: the Debugger process itself and any helper processes like
// gdbserver, the trk client etc are referred to as 'Adapter',
hjk's avatar
hjk committed
113
114
// whereas the debugged process is referred to as 'Inferior'.
//
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
115
//              0 == DebuggerNotReady
hjk's avatar
hjk committed
116
//                          |
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
117
//                    EngineStarting
hjk's avatar
hjk committed
118
//                          |
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
119
//                    AdapterStarting --> AdapterStartFailed --> 0
hjk's avatar
hjk committed
120
//                          |
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//                    AdapterStarted ------------------------------------.
//                          |                                            v
//                   InferiorStarting ----> InferiorStartFailed -------->|
//                          |                                            |
//         (core)           |     (attach) (term) (remote)               |
//      .-----------------<-|->------------------.                       |
//      |                   v                    |                       |
//  InferiorUnrunnable      | (plain)            |                       |
//      |                   | (trk)              |                       |
//      |                   |                    |                       |
//      |    .--> InferiorRunningRequested       |                       |
//      |    |              |                    |                       |
//      |    |       InferiorRunning             |                       |
//      |    |              |                    |                       |
//      |    |       InferiorStopping            |                       |
//      |    |              |                    |                       |
//      |    '------ InferiorStopped <-----------'                       |
//      |                   |                                            v
//      |          InferiorShuttingDown  ->  InferiorShutdownFailed ---->|
//      |                   |                                            |
//      |            InferiorShutDown                                    |
//      |                   |                                            |
//      '-------->  EngineShuttingDown  <--------------------------------'
hjk's avatar
hjk committed
144
145
//                          |
//                          0
hjk's avatar
hjk committed
146
147
148
149
150
151
//
// Allowed actions:
//    [R] :  Run
//    [C] :  Continue
//    [N] :  Step, Next

152
153
namespace Debugger {
namespace Internal {
154

155
156
157
158
159
160
161
IDebuggerEngine *createGdbEngine(DebuggerManager *parent);
IDebuggerEngine *createScriptEngine(DebuggerManager *parent);

// The createWinEngine function takes a list of options pages it can add to.
// This allows for having a "enabled" toggle on the page independently
// of the engine. That's good for not enabling the related ActiveX control
// unnecessarily.
162
163
164
165
166
167
168

IDebuggerEngine *createWinEngine(DebuggerManager *, bool /* cmdLineEnabled */, QList<Core::IOptionsPage*> *)
#ifdef CDB_ENABLED
;
#else
{ return 0; }
#endif
169

170
} // namespace Internal
171

172
DEBUGGER_EXPORT QDebug operator<<(QDebug str, const DebuggerStartParameters &p)
173
174
175
176
177
178
179
180
181
182
{
    QDebug nospace = str.nospace();
    const QString sep = QString(QLatin1Char(','));
    nospace << "executable=" << p.executable << " coreFile=" << p.coreFile
            << " processArgs=" << p.processArgs.join(sep)
            << " environment=<" << p.environment.size() << " variables>"
            << " workingDir=" << p.workingDir << " buildDir=" << p.buildDir
            << " attachPID=" << p.attachPID << " useTerminal=" << p.useTerminal
            << " remoteChannel=" << p.remoteChannel
            << " remoteArchitecture=" << p.remoteArchitecture
183
            << " symbolFileName=" << p.symbolFileName
184
185
            << " serverStartScript=" << p.serverStartScript
            << " toolchain=" << p.toolChainType << '\n';
186
187
188
    return str;
}

189
using namespace Constants;
190
using namespace Debugger::Internal;
191
using namespace TextEditor;
con's avatar
con committed
192
193
194

static const QString tooltipIName = "tooltip";

195
const char *DebuggerManager::stateName(int s)
196
{
hjk's avatar
hjk committed
197
    #define SN(x) case x: return #x;
198
    switch (s) {
hjk's avatar
hjk committed
199
200
201
202
203
204
205
206
        SN(DebuggerNotReady)
        SN(EngineStarting)
        SN(AdapterStarting)
        SN(AdapterStarted)
        SN(AdapterStartFailed)
        SN(InferiorStarting)
        SN(InferiorStartFailed)
        SN(InferiorRunningRequested)
207
        SN(InferiorRunningRequested_Kill)
hjk's avatar
hjk committed
208
        SN(InferiorRunning)
209
        SN(InferiorUnrunnable)
hjk's avatar
hjk committed
210
        SN(InferiorStopping)
211
        SN(InferiorStopping_Kill)
hjk's avatar
hjk committed
212
213
214
215
216
        SN(InferiorStopped)
        SN(InferiorStopFailed)
        SN(InferiorShuttingDown)
        SN(InferiorShutDown)
        SN(InferiorShutdownFailed)
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
217
        SN(EngineShuttingDown)
218
219
    }
    return "<unknown>";
hjk's avatar
hjk committed
220
    #undef SN
221
222
}

con's avatar
con committed
223
224
225

///////////////////////////////////////////////////////////////////////
//
226
// DebuggerStartParameters
con's avatar
con committed
227
228
229
//
///////////////////////////////////////////////////////////////////////

230
231
DebuggerStartParameters::DebuggerStartParameters()
  : attachPID(-1),
232
    useTerminal(false),
hjk's avatar
hjk committed
233
234
    toolChainType(ProjectExplorer::ToolChain::UNKNOWN),
    startMode(NoStartMode)
235
{}
236
237
238

void DebuggerStartParameters::clear()
{
239
    *this = DebuggerStartParameters();
240
241
}

242
243
244
245
246
247
248

///////////////////////////////////////////////////////////////////////
//
// DebuggerManager
//
///////////////////////////////////////////////////////////////////////

249
250
251
static Debugger::Internal::IDebuggerEngine *gdbEngine = 0;
static Debugger::Internal::IDebuggerEngine *scriptEngine = 0;
static Debugger::Internal::IDebuggerEngine *winEngine = 0;
252

253
254
struct DebuggerManagerPrivate
{
255
    explicit DebuggerManagerPrivate(DebuggerManager *manager);
256

257
258
    static DebuggerManager *instance;

con's avatar
con committed
259
260
    QIcon m_stopIcon;
    QIcon m_interruptIcon;
261
262
    const QIcon m_locationMarkIcon;

263
264
265
    // FIXME: Remove engine-specific state
    DebuggerStartParametersPtr m_startParameters;
    qint64 m_inferiorPid;
266

267
    /// Views
268
    DebuggerMainWindow *m_mainWindow;
269

270
    QLabel *m_statusLabel;
271

272
273
274
275
    QDockWidget *m_breakDock;
    QDockWidget *m_modulesDock;
    QDockWidget *m_outputDock;
    QDockWidget *m_registerDock;
276
    QDockWidget *m_snapshotDock;
277
    QDockWidget *m_sourceFilesDock;
278
    QDockWidget *m_stackDock;
279
280
    QDockWidget *m_threadsDock;
    QDockWidget *m_watchDock;
281
    QList<QDockWidget *> m_dockWidgets;
282
283
284
285

    BreakHandler *m_breakHandler;
    ModulesHandler *m_modulesHandler;
    RegisterHandler *m_registerHandler;
286
    SnapshotHandler *m_snapshotHandler;
287
288
289
290
291
292
293
294
295
296
    StackHandler *m_stackHandler;
    ThreadsHandler *m_threadsHandler;
    WatchHandler *m_watchHandler;

    DebuggerManagerActions m_actions;

    QWidget *m_breakWindow;
    QWidget *m_localsWindow;
    QWidget *m_registerWindow;
    QWidget *m_modulesWindow;
297
298
    QWidget *m_snapshotWindow;
    SourceFilesWindow *m_sourceFilesWindow;
299
300
301
302
303
304
305
306
    QWidget *m_stackWindow;
    QWidget *m_threadsWindow;
    QWidget *m_watchersWindow;
    DebuggerOutputWindow *m_outputWindow;

    bool m_busy;
    QTimer *m_statusTimer;
    QString m_lastPermanentStatusMessage;
307
    DisassemblerViewAgent m_disassemblerViewAgent;
308
309
310

    IDebuggerEngine *m_engine;
    DebuggerState m_state;
311
312

    CPlusPlus::Snapshot m_codeModelSnapshot;
313
    DebuggerPlugin *m_plugin;
314
315
};

316
317
DebuggerManager *DebuggerManagerPrivate::instance = 0;

318
DebuggerManagerPrivate::DebuggerManagerPrivate(DebuggerManager *manager) :
con's avatar
con committed
319
320
   m_stopIcon(QLatin1String(":/debugger/images/debugger_stop_small.png")),
   m_interruptIcon(QLatin1String(":/debugger/images/debugger_interrupt_small.png")),
con's avatar
con committed
321
   m_locationMarkIcon(QLatin1String(":/debugger/images/location_16.png")),
322
323
324
325
   m_startParameters(new DebuggerStartParameters),
   m_inferiorPid(0),
   m_disassemblerViewAgent(manager),
   m_engine(0)
326
{
con's avatar
con committed
327
328
    m_interruptIcon.addFile(":/debugger/images/debugger_interrupt.png");
    m_stopIcon.addFile(":/debugger/images/debugger_stop.png");
329
330
}

331
DebuggerManager::DebuggerManager(DebuggerPlugin *plugin)
332
  : d(new DebuggerManagerPrivate(this))
con's avatar
con committed
333
{
334
    DebuggerManagerPrivate::instance = this;
335
    d->m_plugin = plugin;
336
    init();
con's avatar
con committed
337
338
339
340
}

DebuggerManager::~DebuggerManager()
{
341
342
343
    #define doDelete(ptr) delete ptr; ptr = 0
    doDelete(gdbEngine);
    doDelete(scriptEngine);
hjk's avatar
hjk committed
344
    doDelete(winEngine);
345
    #undef doDelete
346
    DebuggerManagerPrivate::instance = 0;
347
    delete d;
con's avatar
con committed
348
349
}

350
351
352
353
354
DebuggerManager *DebuggerManager::instance()
{
    return DebuggerManagerPrivate::instance;
}

355
void DebuggerManager::init()
con's avatar
con committed
356
{
357
358
    d->m_state = DebuggerState(-1);
    d->m_busy = false;
con's avatar
con committed
359

360
361
    d->m_modulesHandler = 0;
    d->m_registerHandler = 0;
con's avatar
con committed
362

363
364
    d->m_statusLabel = new QLabel;
    d->m_statusLabel->setMinimumSize(QSize(30, 10));
365

366
    d->m_breakWindow = new BreakWindow(this);
367
368
369
    d->m_modulesWindow = new ModulesWindow(this);
    d->m_outputWindow = new DebuggerOutputWindow;
    d->m_registerWindow = new RegisterWindow(this);
370
    d->m_snapshotWindow = new SnapshotWindow(this);
371
372
373
374
375
376
    d->m_stackWindow = new StackWindow(this);
    d->m_sourceFilesWindow = new SourceFilesWindow;
    d->m_threadsWindow = new ThreadsWindow;
    d->m_localsWindow = new WatchWindow(WatchWindow::LocalsType, this);
    d->m_watchersWindow = new WatchWindow(WatchWindow::WatchersType, this);
    d->m_statusTimer = new QTimer(this);
con's avatar
con committed
377

378
379
    d->m_mainWindow = qobject_cast<Debugger::Internal::DebuggerMainWindow*>(DebuggerUISwitcher::instance()->mainWindow());
    QTC_ASSERT(d->m_mainWindow, return)
con's avatar
con committed
380

381
382
383
384
385
386
    // Snapshots
    d->m_snapshotHandler = new SnapshotHandler;
    QAbstractItemView *snapshotView =
        qobject_cast<QAbstractItemView *>(d->m_snapshotWindow);
    snapshotView->setModel(d->m_snapshotHandler);

con's avatar
con committed
387
    // Stack
388
    d->m_stackHandler = new StackHandler;
con's avatar
con committed
389
    QAbstractItemView *stackView =
390
391
        qobject_cast<QAbstractItemView *>(d->m_stackWindow);
    stackView->setModel(d->m_stackHandler->stackModel());
392
393
394
395
    connect(theDebuggerAction(ExpandStack), SIGNAL(triggered()),
        this, SLOT(reloadFullStack()));
    connect(theDebuggerAction(MaximalStackDepth), SIGNAL(triggered()),
        this, SLOT(reloadFullStack()));
con's avatar
con committed
396
397

    // Threads
398
    d->m_threadsHandler = new ThreadsHandler;
con's avatar
con committed
399
    QAbstractItemView *threadsView =
400
401
        qobject_cast<QAbstractItemView *>(d->m_threadsWindow);
    threadsView->setModel(d->m_threadsHandler->threadsModel());
con's avatar
con committed
402
403
404
405
    connect(threadsView, SIGNAL(threadSelected(int)),
        this, SLOT(selectThread(int)));

    // Breakpoints
406
    d->m_breakHandler = new BreakHandler(this);
con's avatar
con committed
407
    QAbstractItemView *breakView =
408
409
        qobject_cast<QAbstractItemView *>(d->m_breakWindow);
    breakView->setModel(d->m_breakHandler->model());
410
    connect(breakView, SIGNAL(breakpointActivated(int)),
411
        d->m_breakHandler, SLOT(activateBreakpoint(int)));
412
    connect(breakView, SIGNAL(breakpointDeleted(int)),
413
        d->m_breakHandler, SLOT(removeBreakpoint(int)));
414
415
    connect(breakView, SIGNAL(breakpointSynchronizationRequested()),
        this, SLOT(attemptBreakpointSynchronization()));
416
417
    connect(breakView, SIGNAL(breakByFunctionRequested(QString)),
        this, SLOT(breakByFunction(QString)), Qt::QueuedConnection);
418
419
    connect(breakView, SIGNAL(breakByFunctionMainRequested()),
        this, SLOT(breakByFunctionMain()), Qt::QueuedConnection);
con's avatar
con committed
420
421
422

    // Modules
    QAbstractItemView *modulesView =
423
424
425
        qobject_cast<QAbstractItemView *>(d->m_modulesWindow);
    d->m_modulesHandler = new ModulesHandler;
    modulesView->setModel(d->m_modulesHandler->model());
con's avatar
con committed
426
427
428
429
430
431
    connect(modulesView, SIGNAL(reloadModulesRequested()),
        this, SLOT(reloadModules()));
    connect(modulesView, SIGNAL(loadSymbolsRequested(QString)),
        this, SLOT(loadSymbols(QString)));
    connect(modulesView, SIGNAL(loadAllSymbolsRequested()),
        this, SLOT(loadAllSymbols()));
432
433
    connect(modulesView, SIGNAL(fileOpenRequested(QString)),
        this, SLOT(fileOpen(QString)));
hjk's avatar
hjk committed
434
435
    connect(modulesView, SIGNAL(newDockRequested(QWidget*)),
        this, SLOT(createNewDock(QWidget*)));
con's avatar
con committed
436

437
    // Source Files
438
    //d->m_sourceFilesHandler = new SourceFilesHandler;
439
    QAbstractItemView *sourceFilesView =
440
441
        qobject_cast<QAbstractItemView *>(d->m_sourceFilesWindow);
    //sourceFileView->setModel(d->m_stackHandler->stackModel());
442
443
    connect(sourceFilesView, SIGNAL(reloadSourceFilesRequested()),
        this, SLOT(reloadSourceFiles()));
444
445
    connect(sourceFilesView, SIGNAL(fileOpenRequested(QString)),
        this, SLOT(fileOpen(QString)));
con's avatar
con committed
446

447
    // Registers
con's avatar
con committed
448
    QAbstractItemView *registerView =
449
450
451
        qobject_cast<QAbstractItemView *>(d->m_registerWindow);
    d->m_registerHandler = new RegisterHandler;
    registerView->setModel(d->m_registerHandler->model());
con's avatar
con committed
452

453
    // Locals
454
    d->m_watchHandler = new WatchHandler(this);
455
456
    QTreeView *localsView = qobject_cast<QTreeView *>(d->m_localsWindow);
    localsView->setModel(d->m_watchHandler->model(LocalsWatch));
457
458

    // Watchers
459
460
    QTreeView *watchersView = qobject_cast<QTreeView *>(d->m_watchersWindow);
    watchersView->setModel(d->m_watchHandler->model(WatchersWatch));
461
    connect(theDebuggerAction(AssignValue), SIGNAL(triggered()),
462
        this, SLOT(assignValueInDebugger()), Qt::QueuedConnection);
463
464
    connect(theDebuggerAction(RemoveWatchExpression), SIGNAL(triggered()),
        this, SLOT(updateWatchersWindow()), Qt::QueuedConnection);
con's avatar
con committed
465

466
467
468
469
470
471
    // Log
    connect(this, SIGNAL(emitShowInput(int, QString)),
            d->m_outputWindow, SLOT(showInput(int, QString)), Qt::QueuedConnection);
    connect(this, SIGNAL(emitShowOutput(int, QString)),
            d->m_outputWindow, SLOT(showOutput(int, QString)), Qt::QueuedConnection);

con's avatar
con committed
472
    // Tooltip
473
474
    //QTreeView *tooltipView = qobject_cast<QTreeView *>(d->m_tooltipWindow);
    //tooltipView->setModel(d->m_watchHandler->model(TooltipsWatch));
475
    qRegisterMetaType<WatchData>("WatchData");
hjk's avatar
hjk committed
476
    qRegisterMetaType<StackCookie>("StackCookie");
477

478
    d->m_actions.continueAction = new QAction(tr("Continue"), this);
con's avatar
con committed
479
480
481
    QIcon continueIcon = QIcon(":/debugger/images/debugger_continue_small.png");
    continueIcon.addFile(":/debugger/images/debugger_continue.png");
    d->m_actions.continueAction->setIcon(continueIcon);
con's avatar
con committed
482

483
    d->m_actions.stopAction = new QAction(tr("Interrupt"), this);
con's avatar
con committed
484
    d->m_actions.stopAction->setIcon(d->m_interruptIcon);
con's avatar
con committed
485

486
487
488
    d->m_actions.resetAction = new QAction(tr("Abort Debugging"), this);
    d->m_actions.resetAction->setToolTip(tr("Aborts debugging and "
        "resets the debugger to the initial state."));
con's avatar
con committed
489

490
    d->m_actions.nextAction = new QAction(tr("Step Over"), this);
hjk's avatar
hjk committed
491
492
    d->m_actions.nextAction->setIcon(
        QIcon(":/debugger/images/debugger_stepover_small.png"));
con's avatar
con committed
493

494
    d->m_actions.stepAction = new QAction(tr("Step Into"), this);
hjk's avatar
hjk committed
495
496
    d->m_actions.stepAction->setIcon(
        QIcon(":/debugger/images/debugger_stepinto_small.png"));
con's avatar
con committed
497

498
    d->m_actions.stepOutAction = new QAction(tr("Step Out"), this);
hjk's avatar
hjk committed
499
500
    d->m_actions.stepOutAction->setIcon(
        QIcon(":/debugger/images/debugger_stepout_small.png"));
con's avatar
con committed
501

502
503
    d->m_actions.runToLineAction1 = new QAction(tr("Run to Line"), this);
    d->m_actions.runToLineAction2 = new QAction(tr("Run to Line"), this);
con's avatar
con committed
504

505
506
507
508
509
    d->m_actions.runToFunctionAction =
        new QAction(tr("Run to Outermost Function"), this);

    d->m_actions.returnFromFunctionAction =
        new QAction(tr("Immediately Return From Inner Function"), this);
con's avatar
con committed
510

511
512
    d->m_actions.jumpToLineAction1 = new QAction(tr("Jump to Line"), this);
    d->m_actions.jumpToLineAction2 = new QAction(tr("Jump to Line"), this);
con's avatar
con committed
513

514
    d->m_actions.breakAction = new QAction(tr("Toggle Breakpoint"), this);
con's avatar
con committed
515

516
517
    d->m_actions.watchAction1 = new QAction(tr("Add to Watch Window"), this);
    d->m_actions.watchAction2 = new QAction(tr("Add to Watch Window"), this);
con's avatar
con committed
518

519
    d->m_actions.snapshotAction = new QAction(tr("Snapshot"), this);
hjk's avatar
hjk committed
520
521
    d->m_actions.snapshotAction->setIcon(
        QIcon(":/debugger/images/debugger_snapshot_small.png"));
522

hjk's avatar
hjk committed
523
524
    d->m_actions.reverseDirectionAction =
        new QAction(tr("Reverse Direction"), this);
525
526
    d->m_actions.reverseDirectionAction->setCheckable(true);
    d->m_actions.reverseDirectionAction->setChecked(false);
hjk's avatar
hjk committed
527
    d->m_actions.reverseDirectionAction->setIcon(
hjk's avatar
hjk committed
528
        QIcon(":/debugger/images/debugger_reversemode_16.png"));
529

530
    connect(d->m_actions.continueAction, SIGNAL(triggered()),
hjk's avatar
hjk committed
531
        this, SLOT(executeContinue()));
532
    connect(d->m_actions.stopAction, SIGNAL(triggered()),
con's avatar
con committed
533
        this, SLOT(interruptDebuggingRequest()));
534
    connect(d->m_actions.resetAction, SIGNAL(triggered()),
con's avatar
con committed
535
        this, SLOT(exitDebugger()));
536
    connect(d->m_actions.nextAction, SIGNAL(triggered()),
hjk's avatar
hjk committed
537
        this, SLOT(executeStepNext()));
538
    connect(d->m_actions.stepAction, SIGNAL(triggered()),
hjk's avatar
hjk committed
539
        this, SLOT(executeStep()));
540
    connect(d->m_actions.stepOutAction, SIGNAL(triggered()),
hjk's avatar
hjk committed
541
        this, SLOT(executeStepOut()));
542
    connect(d->m_actions.runToLineAction1, SIGNAL(triggered()),
hjk's avatar
hjk committed
543
        this, SLOT(executeRunToLine()));
544
    connect(d->m_actions.runToLineAction2, SIGNAL(triggered()),
hjk's avatar
hjk committed
545
        this, SLOT(executeRunToLine()));
546
    connect(d->m_actions.runToFunctionAction, SIGNAL(triggered()),
hjk's avatar
hjk committed
547
        this, SLOT(executeRunToFunction()));
548
    connect(d->m_actions.jumpToLineAction1, SIGNAL(triggered()),
hjk's avatar
hjk committed
549
        this, SLOT(executeJumpToLine()));
550
    connect(d->m_actions.jumpToLineAction2, SIGNAL(triggered()),
hjk's avatar
hjk committed
551
        this, SLOT(executeJumpToLine()));
552
    connect(d->m_actions.returnFromFunctionAction, SIGNAL(triggered()),
hjk's avatar
hjk committed
553
        this, SLOT(executeReturn()));
554
555
556
    connect(d->m_actions.watchAction1, SIGNAL(triggered()),
        this, SLOT(addToWatchWindow()));
    connect(d->m_actions.watchAction2, SIGNAL(triggered()),
con's avatar
con committed
557
        this, SLOT(addToWatchWindow()));
558
    connect(d->m_actions.breakAction, SIGNAL(triggered()),
con's avatar
con committed
559
        this, SLOT(toggleBreakpoint()));
560
561
    connect(d->m_actions.snapshotAction, SIGNAL(triggered()),
        this, SLOT(makeSnapshot()));
con's avatar
con committed
562

563
    connect(d->m_statusTimer, SIGNAL(timeout()),
564
        this, SLOT(clearStatusMessage()));
con's avatar
con committed
565

566
567
    connect(theDebuggerAction(ExecuteCommand), SIGNAL(triggered()),
        this, SLOT(executeDebuggerCommand()));
568

569
570
    connect(theDebuggerAction(WatchPoint), SIGNAL(triggered()),
        this, SLOT(watchPoint()));
con's avatar
con committed
571

572
573
    connect(theDebuggerAction(OperateByInstruction), SIGNAL(triggered()),
        this, SLOT(operateByInstructionTriggered()));
574

575
576
577
    DebuggerUISwitcher *uiSwitcher = DebuggerUISwitcher::instance();
    d->m_breakDock = uiSwitcher->createDockWidget(LANG_CPP, d->m_breakWindow);
    d->m_modulesDock = uiSwitcher->createDockWidget(LANG_CPP, d->m_modulesWindow,
hjk's avatar
hjk committed
578
                                                    Qt::TopDockWidgetArea, false);
579

580
    connect(d->m_modulesDock->toggleViewAction(), SIGNAL(toggled(bool)),
con's avatar
con committed
581
582
        this, SLOT(reloadModules()), Qt::QueuedConnection);

583
    d->m_registerDock = uiSwitcher->createDockWidget(LANG_CPP, d->m_registerWindow,
584
        Qt::TopDockWidgetArea, false);
585
    connect(d->m_registerDock->toggleViewAction(), SIGNAL(toggled(bool)),
con's avatar
con committed
586
587
        this, SLOT(reloadRegisters()), Qt::QueuedConnection);

588
    d->m_outputDock = uiSwitcher->createDockWidget(LANG_CPP, d->m_outputWindow,
589
        Qt::TopDockWidgetArea, false);
590

591
592
    d->m_snapshotDock =  uiSwitcher->createDockWidget(LANG_CPP, d->m_snapshotWindow);
    d->m_stackDock = uiSwitcher->createDockWidget(LANG_CPP, d->m_stackWindow);
593
594
    d->m_sourceFilesDock = uiSwitcher->createDockWidget(LANG_CPP,
        d->m_sourceFilesWindow, Qt::TopDockWidgetArea, false);
595
    connect(d->m_sourceFilesDock->toggleViewAction(), SIGNAL(toggled(bool)),
596
597
        this, SLOT(reloadSourceFiles()), Qt::QueuedConnection);

598
    d->m_threadsDock = uiSwitcher->createDockWidget(LANG_CPP, d->m_threadsWindow);
con's avatar
con committed
599

600
    QSplitter *localsAndWatchers = new Core::MiniSplitter(Qt::Vertical);
601
602
603
604
    localsAndWatchers->setWindowTitle(d->m_localsWindow->windowTitle());
    localsAndWatchers->addWidget(d->m_localsWindow);
    localsAndWatchers->addWidget(d->m_watchersWindow);
    //localsAndWatchers->addWidget(d->m_tooltipWindow);
605
606
    localsAndWatchers->setStretchFactor(0, 3);
    localsAndWatchers->setStretchFactor(1, 1);
607
    localsAndWatchers->setStretchFactor(2, 1);
608
609
    d->m_watchDock = DebuggerUISwitcher::instance()->createDockWidget(LANG_CPP,
        localsAndWatchers);
610
611
612
    d->m_dockWidgets << d->m_breakDock << d->m_modulesDock << d->m_registerDock
                     << d->m_outputDock << d->m_stackDock << d->m_sourceFilesDock
                     << d->m_threadsDock << d->m_watchDock;
613

hjk's avatar
hjk committed
614
    setState(DebuggerNotReady);
615
616
}

617
QList<Core::IOptionsPage*> DebuggerManager::initializeEngines(unsigned enabledTypeFlags)
618
619
{
    QList<Core::IOptionsPage*> rc;
620

621
622
623
624
    if (enabledTypeFlags & GdbEngineType) {
        gdbEngine = createGdbEngine(this);
        gdbEngine->addOptionPages(&rc);
    }
625

626
    winEngine = createWinEngine(this, (enabledTypeFlags & CdbEngineType), &rc);
627
628
629
630
631
632

    if (enabledTypeFlags & ScriptEngineType) {
        scriptEngine = createScriptEngine(this);
        scriptEngine->addOptionPages(&rc);
    }

633
    d->m_engine = 0;
634
    STATE_DEBUG(gdbEngine << winEngine << scriptEngine << rc.size());
635
    return rc;
con's avatar
con committed
636
637
}

638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
DebuggerManagerActions DebuggerManager::debuggerManagerActions() const
{
    return d->m_actions;
}

QLabel *DebuggerManager::statusLabel() const
{
    return d->m_statusLabel;
}

IDebuggerEngine *DebuggerManager::currentEngine() const
{
    return d->m_engine;
}

ModulesHandler *DebuggerManager::modulesHandler() const
{
    return d->m_modulesHandler;
}

BreakHandler *DebuggerManager::breakHandler() const
{
    return d->m_breakHandler;
}

RegisterHandler *DebuggerManager::registerHandler() const
{
    return d->m_registerHandler;
}

StackHandler *DebuggerManager::stackHandler() const
{
    return d->m_stackHandler;
}

ThreadsHandler *DebuggerManager::threadsHandler() const
{
    return d->m_threadsHandler;
}

WatchHandler *DebuggerManager::watchHandler() const
{
    return d->m_watchHandler;
}

683
684
685
686
687
SnapshotHandler *DebuggerManager::snapshotHandler() const
{
    return d->m_snapshotHandler;
}

688
689
690
691
692
693
694
695
696
const CPlusPlus::Snapshot &DebuggerManager::cppCodeModelSnapshot() const
{
    if (d->m_codeModelSnapshot.isEmpty() && theDebuggerAction(UseCodeModel)->isChecked())
        d->m_codeModelSnapshot = CppTools::CppModelManagerInterface::instance()->snapshot();
    return d->m_codeModelSnapshot;
}

void DebuggerManager::clearCppCodeModelSnapshot()
{
697
    d->m_codeModelSnapshot = CPlusPlus::Snapshot();
698
699
}

700
701
702
703
704
705
SourceFilesWindow *DebuggerManager::sourceFileWindow() const
{
    return d->m_sourceFilesWindow;
}

QWidget *DebuggerManager::threadsWindow() const
con's avatar
con committed
706
{
707
    return d->m_threadsWindow;
con's avatar
con committed
708
709
}

hjk's avatar
hjk committed
710
711
void DebuggerManager::createNewDock(QWidget *widget)
{
712
713
    QDockWidget *dockWidget =
        DebuggerUISwitcher::instance()->createDockWidget(LANG_CPP, widget);
714
    dockWidget->setWindowTitle(widget->windowTitle());
hjk's avatar
hjk committed
715
716
    dockWidget->setObjectName(widget->windowTitle());
    dockWidget->setFeatures(QDockWidget::DockWidgetClosable);
717
718
    //dockWidget->setWidget(widget);
    //d->m_mainWindow->addDockWidget(Qt::TopDockWidgetArea, dockWidget);
hjk's avatar
hjk committed
719
720
721
    dockWidget->show();
}

722
void DebuggerManager::setSimpleDockWidgetArrangement(const QString &activeLanguage)
con's avatar
con committed
723
{
hjk's avatar
hjk committed
724
    if (activeLanguage == LANG_CPP || activeLanguage.isEmpty()) {
725
726
727
728
729
730
731
732
        d->m_mainWindow->setTrackingEnabled(false);
        QList<QDockWidget *> dockWidgets = d->m_mainWindow->dockWidgets();
        foreach (QDockWidget *dockWidget, dockWidgets) {
            if (d->m_dockWidgets.contains(dockWidget)) {
                dockWidget->setFloating(false);
                d->m_mainWindow->removeDockWidget(dockWidget);
            }
        }
con's avatar
con committed
733

734
735
736
737
738
739
740
741
742
        foreach (QDockWidget *dockWidget, dockWidgets) {
            if (d->m_dockWidgets.contains(dockWidget)) {
                if (dockWidget == d->m_outputDock)
                    d->m_mainWindow->addDockWidget(Qt::TopDockWidgetArea, dockWidget);
                else
                    d->m_mainWindow->addDockWidget(Qt::BottomDockWidgetArea, dockWidget);
                dockWidget->show();
            }
        }
con's avatar
con committed
743

744
745
746
747
748
749
750
751
752
753
754
755
756
757
        d->m_mainWindow->tabifyDockWidget(d->m_watchDock, d->m_breakDock);
        d->m_mainWindow->tabifyDockWidget(d->m_watchDock, d->m_modulesDock);
        d->m_mainWindow->tabifyDockWidget(d->m_watchDock, d->m_registerDock);
        d->m_mainWindow->tabifyDockWidget(d->m_watchDock, d->m_threadsDock);
        d->m_mainWindow->tabifyDockWidget(d->m_watchDock, d->m_sourceFilesDock);
        d->m_mainWindow->tabifyDockWidget(d->m_watchDock, d->m_snapshotDock);
        // They following views are rarely used in ordinary debugging. Hiding them
        // saves cycles since the corresponding information won't be retrieved.
        d->m_sourceFilesDock->hide();
        d->m_registerDock->hide();
        d->m_modulesDock->hide();
        d->m_outputDock->hide();
        d->m_mainWindow->setTrackingEnabled(true);
    }
con's avatar
con committed
758
759
760
761
}

QAbstractItemModel *DebuggerManager::threadsModel()
{
762
    return qobject_cast<ThreadsWindow*>(d->m_threadsWindow)->model();
con's avatar
con committed
763
764
}

765
766
void DebuggerManager::clearStatusMessage()
{
767
    d->m_statusLabel->setText(d->m_lastPermanentStatusMessage);
768
769
}

770
void DebuggerManager::showStatusMessage(const QString &msg0, int timeout)
con's avatar
con committed
771
772
{
    Q_UNUSED(timeout)
773
774
775
    showDebuggerOutput(LogStatus, msg0);
    QString msg = msg0;
    msg.replace(QLatin1Char('\n'), QString());
776
    d->m_statusLabel->setText(msg);
777
    if (timeout > 0) {
778
779
        d->m_statusTimer->setSingleShot(true);
        d->m_statusTimer->start(timeout);
780
    } else {
781
782
        d->m_lastPermanentStatusMessage = msg;
        d->m_statusTimer->stop();
783
    }
con's avatar
con committed
784
785
786
787
}

void DebuggerManager::notifyInferiorStopped()
{
hjk's avatar
hjk committed
788
    setState(InferiorStopped);
789
    showStatusMessage(tr("Stopped"), 5000);
con's avatar
con committed
790
791
792
793
}

void DebuggerManager::notifyInferiorRunning()
{
hjk's avatar
hjk committed
794
    setState(InferiorRunning);
con's avatar
con committed
795
796
797
798
799
    showStatusMessage(tr("Running..."), 5000);
}

void DebuggerManager::notifyInferiorExited()
{
hjk's avatar
hjk committed
800
    setState(DebuggerNotReady);
801
    showStatusMessage(tr("Exited"), 5000);
con's avatar
con committed
802
803
}

804
void DebuggerManager::notifyInferiorPidChanged(qint64 pid)
con's avatar
con committed
805
{
806
    STATE_DEBUG(d->m_inferiorPid << pid);
807

808
809
    if (d->m_inferiorPid != pid) {
        d->m_inferiorPid = pid;
810
811
        emit inferiorPidChanged(pid);
    }
con's avatar
con committed
812
813
}

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
814
void DebuggerManager::showApplicationOutput(const QString &str)
con's avatar
con committed
815
{
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
816
     emit applicationOutputAvailable(str);
con's avatar
con committed
817
818
819
820
}

void DebuggerManager::shutdown()
{
821
822
823
824
    STATE_DEBUG(d->m_engine);
    if (d->m_engine)
        d->m_engine->shutdown();
    d->m_engine = 0;
825

826
827
828
829
    #define doDelete(ptr) delete ptr; ptr = 0
    doDelete(scriptEngine);
    doDelete(gdbEngine);
    doDelete(winEngine);
830

con's avatar
con committed
831
832
    // Delete these manually before deleting the manager
    // (who will delete the models for most views)
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
    doDelete(d->m_breakWindow);
    doDelete(d->m_modulesWindow);
    doDelete(d->m_outputWindow);
    doDelete(d->m_registerWindow);
    doDelete(d->m_stackWindow);
    doDelete(d->m_sourceFilesWindow);
    doDelete(d->m_threadsWindow);
    //doDelete(d->m_tooltipWindow);
    doDelete(d->m_watchersWindow);
    doDelete(d->m_localsWindow);

    doDelete(d->m_breakHandler);
    doDelete(d->m_threadsHandler);
    doDelete(d->m_modulesHandler);
    doDelete(d->m_registerHandler);
848
    doDelete(d->m_snapshotHandler);
849
850
    doDelete(d->m_stackHandler);
    doDelete(d->m_watchHandler);
851
    #undef doDelete
con's avatar
con committed
852
853
}

854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
void DebuggerManager::makeSnapshot()
{
    QTC_ASSERT(d->m_engine, return);
    d->m_engine->makeSnapshot();
}

void DebuggerManager::activateSnapshot(int index)
{
    QTC_ASSERT(d->m_engine, return);
    d->m_engine->activateSnapshot(index);
}

void DebuggerManager::removeSnapshot(int index)
{
    QTC_ASSERT(d->m_engine, return);
    d->m_snapshotHandler->removeSnapshot(index);
}

872
873
BreakpointData *DebuggerManager::findBreakpoint(const QString &fileName, int lineNumber)
{
874
    if (!d->m_breakHandler)
875
        return 0;
876
877
    int index = d->m_breakHandler->findBreakpoint(fileName, lineNumber);
    return index == -1 ? 0 : d->m_breakHandler->at(index);
878
879
}

con's avatar
con committed
880
881
void DebuggerManager::toggleBreakpoint()
{
882
883
884
885
886
887
    ITextEditor *textEditor = d->m_plugin->currentTextEditor();
    QTC_ASSERT(textEditor, return);
    QString fileName = textEditor->file()->fileName();
    int lineNumber = textEditor->currentLine();
    if (lineNumber >= 0)
        toggleBreakpoint(fileName, lineNumber);
con's avatar
con committed
888
889
890
891
}

void DebuggerManager::toggleBreakpoint(const QString &fileName, int lineNumber)
{
892
    STATE_DEBUG(fileName << lineNumber);
893
    QTC_ASSERT(d->m_breakHandler, return);
hjk's avatar
hjk committed
894
895
896
    if (state() != InferiorRunning
         && state() != InferiorStopped
         && state() != DebuggerNotReady) {
897
898
899
900
901
        showStatusMessage(tr("Changing breakpoint state requires either a "
            "fully running or fully stopped application."));
        return;
    }

902
    int index = d->m_breakHandler->findBreakpoint(fileName, lineNumber);
con's avatar
con committed
903
    if (index == -1)
904
        d->m_breakHandler->setBreakpoint(fileName, lineNumber);
con's avatar
con committed
905
    else
906
        d->m_breakHandler->removeBreakpoint(index);
907

hjk's avatar
hjk committed
908
    attemptBreakpointSynchronization();
con's avatar
con committed
909
910
}

911
912
void DebuggerManager::toggleBreakpointEnabled(const QString &fileName, int lineNumber)
{
913
    STATE_DEBUG(fileName << lineNumber);
914
    QTC_ASSERT(d->m_breakHandler, return);
hjk's avatar
hjk committed
915
916
917
    if (state() != InferiorRunning
         && state() != InferiorStopped
         && state() != DebuggerNotReady) {
918
919
920
921
922
        showStatusMessage(tr("Changing breakpoint state requires either a "
            "fully running or fully stopped application."));
        return;
    }

923
    d->m_breakHandler->toggleBreakpointEnabled(fileName, lineNumber);
hjk's avatar
hjk committed
924
925

    attemptBreakpointSynchronization();
926
927
}

928
929
void DebuggerManager::attemptBreakpointSynchronization()
{