debuggermanager.cpp 64.8 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
    d->m_breakWindow->setObjectName(QLatin1String("CppDebugBreakpoints"));
368
    d->m_modulesWindow = new ModulesWindow(this);
369
    d->m_modulesWindow->setObjectName(QLatin1String("CppDebugModules"));
370
    d->m_outputWindow = new DebuggerOutputWindow;
371
372
    d->m_outputWindow->setObjectName(QLatin1String("CppDebugOutput"));

373
    d->m_registerWindow = new RegisterWindow(this);
374
    d->m_registerWindow->setObjectName(QLatin1String("CppDebugRegisters"));
375
    d->m_snapshotWindow = new SnapshotWindow(this);
376
    d->m_snapshotWindow->setObjectName(QLatin1String("CppDebugSnapshots"));
377
    d->m_stackWindow = new StackWindow(this);
378
    d->m_stackWindow->setObjectName(QLatin1String("CppDebugStack"));
379
    d->m_sourceFilesWindow = new SourceFilesWindow;
380
    d->m_sourceFilesWindow->setObjectName(QLatin1String("CppDebugSources"));
381
    d->m_threadsWindow = new ThreadsWindow;
382
    d->m_threadsWindow->setObjectName(QLatin1String("CppDebugThreads"));
383
    d->m_localsWindow = new WatchWindow(WatchWindow::LocalsType, this);
384
    d->m_localsWindow->setObjectName(QLatin1String("CppDebugLocals"));
385
    d->m_watchersWindow = new WatchWindow(WatchWindow::WatchersType, this);
386
    d->m_watchersWindow->setObjectName(QLatin1String("CppDebugWatchers"));
387
    d->m_statusTimer = new QTimer(this);
con's avatar
con committed
388

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

392
393
394
395
396
397
    // Snapshots
    d->m_snapshotHandler = new SnapshotHandler;
    QAbstractItemView *snapshotView =
        qobject_cast<QAbstractItemView *>(d->m_snapshotWindow);
    snapshotView->setModel(d->m_snapshotHandler);

con's avatar
con committed
398
    // Stack
399
    d->m_stackHandler = new StackHandler;
con's avatar
con committed
400
    QAbstractItemView *stackView =
401
402
        qobject_cast<QAbstractItemView *>(d->m_stackWindow);
    stackView->setModel(d->m_stackHandler->stackModel());
403
404
405
406
    connect(theDebuggerAction(ExpandStack), SIGNAL(triggered()),
        this, SLOT(reloadFullStack()));
    connect(theDebuggerAction(MaximalStackDepth), SIGNAL(triggered()),
        this, SLOT(reloadFullStack()));
con's avatar
con committed
407
408

    // Threads
409
    d->m_threadsHandler = new ThreadsHandler;
con's avatar
con committed
410
    QAbstractItemView *threadsView =
411
412
        qobject_cast<QAbstractItemView *>(d->m_threadsWindow);
    threadsView->setModel(d->m_threadsHandler->threadsModel());
con's avatar
con committed
413
414
415
416
    connect(threadsView, SIGNAL(threadSelected(int)),
        this, SLOT(selectThread(int)));

    // Breakpoints
417
    d->m_breakHandler = new BreakHandler(this);
con's avatar
con committed
418
    QAbstractItemView *breakView =
419
420
        qobject_cast<QAbstractItemView *>(d->m_breakWindow);
    breakView->setModel(d->m_breakHandler->model());
421
    connect(breakView, SIGNAL(breakpointActivated(int)),
hjk's avatar
hjk committed
422
        this, SLOT(activateBreakpoint(int)));
423
    connect(breakView, SIGNAL(breakpointDeleted(int)),
424
        d->m_breakHandler, SLOT(removeBreakpoint(int)));
425
426
    connect(breakView, SIGNAL(breakpointSynchronizationRequested()),
        this, SLOT(attemptBreakpointSynchronization()));
427
428
    connect(breakView, SIGNAL(breakByFunctionRequested(QString)),
        this, SLOT(breakByFunction(QString)), Qt::QueuedConnection);
429
430
    connect(breakView, SIGNAL(breakByFunctionMainRequested()),
        this, SLOT(breakByFunctionMain()), Qt::QueuedConnection);
con's avatar
con committed
431
432
433

    // Modules
    QAbstractItemView *modulesView =
434
435
436
        qobject_cast<QAbstractItemView *>(d->m_modulesWindow);
    d->m_modulesHandler = new ModulesHandler;
    modulesView->setModel(d->m_modulesHandler->model());
con's avatar
con committed
437
438
439
440
441
442
    connect(modulesView, SIGNAL(reloadModulesRequested()),
        this, SLOT(reloadModules()));
    connect(modulesView, SIGNAL(loadSymbolsRequested(QString)),
        this, SLOT(loadSymbols(QString)));
    connect(modulesView, SIGNAL(loadAllSymbolsRequested()),
        this, SLOT(loadAllSymbols()));
443
444
    connect(modulesView, SIGNAL(fileOpenRequested(QString)),
        this, SLOT(fileOpen(QString)));
hjk's avatar
hjk committed
445
446
    connect(modulesView, SIGNAL(newDockRequested(QWidget*)),
        this, SLOT(createNewDock(QWidget*)));
con's avatar
con committed
447

448
    // Source Files
449
    //d->m_sourceFilesHandler = new SourceFilesHandler;
450
    QAbstractItemView *sourceFilesView =
451
452
        qobject_cast<QAbstractItemView *>(d->m_sourceFilesWindow);
    //sourceFileView->setModel(d->m_stackHandler->stackModel());
453
454
    connect(sourceFilesView, SIGNAL(reloadSourceFilesRequested()),
        this, SLOT(reloadSourceFiles()));
455
456
    connect(sourceFilesView, SIGNAL(fileOpenRequested(QString)),
        this, SLOT(fileOpen(QString)));
con's avatar
con committed
457

458
    // Registers
con's avatar
con committed
459
    QAbstractItemView *registerView =
460
461
462
        qobject_cast<QAbstractItemView *>(d->m_registerWindow);
    d->m_registerHandler = new RegisterHandler;
    registerView->setModel(d->m_registerHandler->model());
con's avatar
con committed
463

464
    // Locals
465
    d->m_watchHandler = new WatchHandler(this);
466
467
    QTreeView *localsView = qobject_cast<QTreeView *>(d->m_localsWindow);
    localsView->setModel(d->m_watchHandler->model(LocalsWatch));
468
469

    // Watchers
470
471
    QTreeView *watchersView = qobject_cast<QTreeView *>(d->m_watchersWindow);
    watchersView->setModel(d->m_watchHandler->model(WatchersWatch));
472
    connect(theDebuggerAction(AssignValue), SIGNAL(triggered()),
473
        this, SLOT(assignValueInDebugger()), Qt::QueuedConnection);
474
475
    connect(theDebuggerAction(RemoveWatchExpression), SIGNAL(triggered()),
        this, SLOT(updateWatchersWindow()), Qt::QueuedConnection);
con's avatar
con committed
476

477
478
479
480
481
482
    // 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
483
    // Tooltip
484
485
    //QTreeView *tooltipView = qobject_cast<QTreeView *>(d->m_tooltipWindow);
    //tooltipView->setModel(d->m_watchHandler->model(TooltipsWatch));
486
    qRegisterMetaType<WatchData>("WatchData");
hjk's avatar
hjk committed
487
    qRegisterMetaType<StackCookie>("StackCookie");
488

489
    d->m_actions.continueAction = new QAction(tr("Continue"), this);
con's avatar
con committed
490
491
492
    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
493

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

497
498
499
    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
500

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

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

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

513
514
    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
515

516
517
518
519
520
    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
521

522
523
    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
524

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

527
528
    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
529

530
    d->m_actions.snapshotAction = new QAction(tr("Snapshot"), this);
hjk's avatar
hjk committed
531
532
    d->m_actions.snapshotAction->setIcon(
        QIcon(":/debugger/images/debugger_snapshot_small.png"));
533

hjk's avatar
hjk committed
534
535
    d->m_actions.reverseDirectionAction =
        new QAction(tr("Reverse Direction"), this);
536
537
    d->m_actions.reverseDirectionAction->setCheckable(true);
    d->m_actions.reverseDirectionAction->setChecked(false);
hjk's avatar
hjk committed
538
    d->m_actions.reverseDirectionAction->setIcon(
hjk's avatar
hjk committed
539
        QIcon(":/debugger/images/debugger_reversemode_16.png"));
540

541
    connect(d->m_actions.continueAction, SIGNAL(triggered()),
hjk's avatar
hjk committed
542
        this, SLOT(executeContinue()));
543
    connect(d->m_actions.stopAction, SIGNAL(triggered()),
con's avatar
con committed
544
        this, SLOT(interruptDebuggingRequest()));
545
    connect(d->m_actions.resetAction, SIGNAL(triggered()),
546
        this, SLOT(abortDebugger()));
547
    connect(d->m_actions.nextAction, SIGNAL(triggered()),
hjk's avatar
hjk committed
548
        this, SLOT(executeStepNext()));
549
    connect(d->m_actions.stepAction, SIGNAL(triggered()),
hjk's avatar
hjk committed
550
        this, SLOT(executeStep()));
551
    connect(d->m_actions.stepOutAction, SIGNAL(triggered()),
hjk's avatar
hjk committed
552
        this, SLOT(executeStepOut()));
553
    connect(d->m_actions.runToLineAction1, SIGNAL(triggered()),
hjk's avatar
hjk committed
554
        this, SLOT(executeRunToLine()));
555
    connect(d->m_actions.runToLineAction2, SIGNAL(triggered()),
hjk's avatar
hjk committed
556
        this, SLOT(executeRunToLine()));
557
    connect(d->m_actions.runToFunctionAction, SIGNAL(triggered()),
hjk's avatar
hjk committed
558
        this, SLOT(executeRunToFunction()));
559
    connect(d->m_actions.jumpToLineAction1, SIGNAL(triggered()),
hjk's avatar
hjk committed
560
        this, SLOT(executeJumpToLine()));
561
    connect(d->m_actions.jumpToLineAction2, SIGNAL(triggered()),
hjk's avatar
hjk committed
562
        this, SLOT(executeJumpToLine()));
563
    connect(d->m_actions.returnFromFunctionAction, SIGNAL(triggered()),
hjk's avatar
hjk committed
564
        this, SLOT(executeReturn()));
565
566
567
    connect(d->m_actions.watchAction1, SIGNAL(triggered()),
        this, SLOT(addToWatchWindow()));
    connect(d->m_actions.watchAction2, SIGNAL(triggered()),
con's avatar
con committed
568
        this, SLOT(addToWatchWindow()));
569
570
    connect(d->m_actions.snapshotAction, SIGNAL(triggered()),
        this, SLOT(makeSnapshot()));
con's avatar
con committed
571

572
    connect(d->m_statusTimer, SIGNAL(timeout()),
573
        this, SLOT(clearStatusMessage()));
con's avatar
con committed
574

575
576
    connect(theDebuggerAction(ExecuteCommand), SIGNAL(triggered()),
        this, SLOT(executeDebuggerCommand()));
577

578
579
    connect(theDebuggerAction(WatchPoint), SIGNAL(triggered()),
        this, SLOT(watchPoint()));
con's avatar
con committed
580

581
582
    connect(theDebuggerAction(OperateByInstruction), SIGNAL(triggered()),
        this, SLOT(operateByInstructionTriggered()));
583

584
585
586
    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
587
                                                    Qt::TopDockWidgetArea, false);
588

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

592
    d->m_registerDock = uiSwitcher->createDockWidget(LANG_CPP, d->m_registerWindow,
593
        Qt::TopDockWidgetArea, false);
594
    connect(d->m_registerDock->toggleViewAction(), SIGNAL(toggled(bool)),
con's avatar
con committed
595
596
        this, SLOT(reloadRegisters()), Qt::QueuedConnection);

597
    d->m_outputDock = uiSwitcher->createDockWidget(LANG_CPP, d->m_outputWindow,
598
        Qt::TopDockWidgetArea, false);
599

600
601
    d->m_snapshotDock =  uiSwitcher->createDockWidget(LANG_CPP, d->m_snapshotWindow);
    d->m_stackDock = uiSwitcher->createDockWidget(LANG_CPP, d->m_stackWindow);
602
603
    d->m_sourceFilesDock = uiSwitcher->createDockWidget(LANG_CPP,
        d->m_sourceFilesWindow, Qt::TopDockWidgetArea, false);
604
    connect(d->m_sourceFilesDock->toggleViewAction(), SIGNAL(toggled(bool)),
605
606
        this, SLOT(reloadSourceFiles()), Qt::QueuedConnection);

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

609
    QSplitter *localsAndWatchers = new Core::MiniSplitter(Qt::Vertical);
610
    localsAndWatchers->setObjectName(QLatin1String("CppDebugLocalsAndWatchers"));
611
612
613
614
    localsAndWatchers->setWindowTitle(d->m_localsWindow->windowTitle());
    localsAndWatchers->addWidget(d->m_localsWindow);
    localsAndWatchers->addWidget(d->m_watchersWindow);
    //localsAndWatchers->addWidget(d->m_tooltipWindow);
615
616
    localsAndWatchers->setStretchFactor(0, 3);
    localsAndWatchers->setStretchFactor(1, 1);
617
    localsAndWatchers->setStretchFactor(2, 1);
618
619
    d->m_watchDock = DebuggerUISwitcher::instance()->createDockWidget(LANG_CPP,
        localsAndWatchers);
620
621
622
    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;
623

hjk's avatar
hjk committed
624
    setState(DebuggerNotReady);
625
626
}

627
QList<Core::IOptionsPage*> DebuggerManager::initializeEngines(unsigned enabledTypeFlags)
628
629
{
    QList<Core::IOptionsPage*> rc;
630

631
632
633
634
    if (enabledTypeFlags & GdbEngineType) {
        gdbEngine = createGdbEngine(this);
        gdbEngine->addOptionPages(&rc);
    }
635

636
    winEngine = createWinEngine(this, (enabledTypeFlags & CdbEngineType), &rc);
637
638
639
640
641
642

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

643
    d->m_engine = 0;
644
    STATE_DEBUG(gdbEngine << winEngine << scriptEngine << rc.size());
645
    return rc;
con's avatar
con committed
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
683
684
685
686
687
688
689
690
691
692
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;
}

693
694
695
696
697
SnapshotHandler *DebuggerManager::snapshotHandler() const
{
    return d->m_snapshotHandler;
}

698
699
700
701
702
703
704
705
706
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()
{
707
    d->m_codeModelSnapshot = CPlusPlus::Snapshot();
708
709
}

710
711
712
713
714
715
SourceFilesWindow *DebuggerManager::sourceFileWindow() const
{
    return d->m_sourceFilesWindow;
}

QWidget *DebuggerManager::threadsWindow() const
con's avatar
con committed
716
{
717
    return d->m_threadsWindow;
con's avatar
con committed
718
719
}

hjk's avatar
hjk committed
720
721
void DebuggerManager::createNewDock(QWidget *widget)
{
722
723
    QDockWidget *dockWidget =
        DebuggerUISwitcher::instance()->createDockWidget(LANG_CPP, widget);
724
    dockWidget->setWindowTitle(widget->windowTitle());
hjk's avatar
hjk committed
725
726
    dockWidget->setObjectName(widget->windowTitle());
    dockWidget->setFeatures(QDockWidget::DockWidgetClosable);
727
728
    //dockWidget->setWidget(widget);
    //d->m_mainWindow->addDockWidget(Qt::TopDockWidgetArea, dockWidget);
hjk's avatar
hjk committed
729
730
731
    dockWidget->show();
}

732
void DebuggerManager::setSimpleDockWidgetArrangement(const QString &activeLanguage)
con's avatar
con committed
733
{
hjk's avatar
hjk committed
734
    if (activeLanguage == LANG_CPP || activeLanguage.isEmpty()) {
735
736
737
738
739
740
741
742
        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
743

744
745
746
747
748
749
750
751
752
        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
753

754
755
756
757
758
759
760
761
762
763
764
765
766
767
        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
768
769
770
771
}

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

775
776
void DebuggerManager::clearStatusMessage()
{
777
    d->m_statusLabel->setText(d->m_lastPermanentStatusMessage);
778
779
}

780
void DebuggerManager::showStatusMessage(const QString &msg0, int timeout)
con's avatar
con committed
781
782
{
    Q_UNUSED(timeout)
783
784
785
    showDebuggerOutput(LogStatus, msg0);
    QString msg = msg0;
    msg.replace(QLatin1Char('\n'), QString());
786
    d->m_statusLabel->setText(msg);
787
    if (timeout > 0) {
788
789
        d->m_statusTimer->setSingleShot(true);
        d->m_statusTimer->start(timeout);
790
    } else {
791
792
        d->m_lastPermanentStatusMessage = msg;
        d->m_statusTimer->stop();
793
    }
con's avatar
con committed
794
795
796
797
}

void DebuggerManager::notifyInferiorStopped()
{
hjk's avatar
hjk committed
798
    setState(InferiorStopped);
799
    showStatusMessage(tr("Stopped"), 5000);
con's avatar
con committed
800
801
802
803
}

void DebuggerManager::notifyInferiorRunning()
{
hjk's avatar
hjk committed
804
    setState(InferiorRunning);
con's avatar
con committed
805
806
807
808
809
    showStatusMessage(tr("Running..."), 5000);
}

void DebuggerManager::notifyInferiorExited()
{
hjk's avatar
hjk committed
810
    setState(DebuggerNotReady);
811
    showStatusMessage(tr("Exited"), 5000);
con's avatar
con committed
812
813
}

814
void DebuggerManager::notifyInferiorPidChanged(qint64 pid)
con's avatar
con committed
815
{
816
    STATE_DEBUG(d->m_inferiorPid << pid);
817

818
819
    if (d->m_inferiorPid != pid) {
        d->m_inferiorPid = pid;
820
821
        emit inferiorPidChanged(pid);
    }
con's avatar
con committed
822
823
}

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
824
void DebuggerManager::showApplicationOutput(const QString &str)
con's avatar
con committed
825
{
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
826
     emit applicationOutputAvailable(str);
con's avatar
con committed
827
828
829
830
}

void DebuggerManager::shutdown()
{
831
832
833
834
    STATE_DEBUG(d->m_engine);
    if (d->m_engine)
        d->m_engine->shutdown();
    d->m_engine = 0;
835

836
837
838
839
    #define doDelete(ptr) delete ptr; ptr = 0
    doDelete(scriptEngine);
    doDelete(gdbEngine);
    doDelete(winEngine);
840

con's avatar
con committed
841
842
    // Delete these manually before deleting the manager
    // (who will delete the models for most views)
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
    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);
858
    doDelete(d->m_snapshotHandler);
859
860
    doDelete(d->m_stackHandler);
    doDelete(d->m_watchHandler);
861
    #undef doDelete
con's avatar
con committed
862
863
}

864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
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);
}

882
883
BreakpointData *DebuggerManager::findBreakpoint(const QString &fileName, int lineNumber)
{
884
    if (!d->m_breakHandler)
885
        return 0;
886
887
    int index = d->m_breakHandler->findBreakpoint(fileName, lineNumber);
    return index == -1 ? 0 : d->m_breakHandler->at(index);
888
889
}

890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
// FIXME: move further up the plugin where there's more specific context
// information available.
static BreakpointData *createBreakpointByFileAndLine
    (const QString &fileName, int lineNumber, BreakHandler *handler)
{
    BreakpointData *data = new BreakpointData(handler);
    if (lineNumber > 0) {
        data->fileName = fileName;
        data->lineNumber = QByteArray::number(lineNumber);
        data->pending = true;
        data->setMarkerFileName(fileName);
        data->setMarkerLineNumber(lineNumber);
    } else {
        data->funcName = fileName;
        data->lineNumber = 0;
        data->pending = true;
        // FIXME: Figure out in which disassembler view the Marker sits.
        // Might be better to let the user code create the BreakpointData
        // structure and insert it here.
        data->setMarkerFileName(QString());
        data->setMarkerLineNumber(0);
    }
    return data;
}

con's avatar
con committed
915
916
void DebuggerManager::toggleBreakpoint(const QString &fileName, int lineNumber)
{
917
    STATE_DEBUG(fileName << lineNumber);