debuggerplugin.cpp 48.2 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
**************************************************************************/
hjk's avatar
hjk committed
29

con's avatar
con committed
30
31
#include "debuggerplugin.h"

32
#include "breakhandler.h"
33
#include "debuggeractions.h"
34
#include "debuggerdialogs.h"
con's avatar
con committed
35
36
37
#include "debuggerconstants.h"
#include "debuggermanager.h"
#include "debuggerrunner.h"
38
#include "debuggerstringutils.h"
39
40
#include "debuggeruiswitcher.h"
#include "debuggermainwindow.h"
con's avatar
con committed
41

42
#include "ui_commonoptionspage.h"
hjk's avatar
hjk committed
43
#include "ui_dumperoptionpage.h"
44

45
#include <coreplugin/actionmanager/actionmanager.h>
hjk's avatar
hjk committed
46
#include <coreplugin/basemode.h>
con's avatar
con committed
47
#include <coreplugin/coreconstants.h>
48
#include <coreplugin/dialogs/ioptionspage.h>
con's avatar
con committed
49
#include <coreplugin/editormanager/editormanager.h>
hjk's avatar
hjk committed
50
#include <coreplugin/findplaceholder.h>
con's avatar
con committed
51
#include <coreplugin/icore.h>
52
#include <coreplugin/icorelistener.h>
con's avatar
con committed
53
#include <coreplugin/messagemanager.h>
hjk's avatar
hjk committed
54
#include <coreplugin/minisplitter.h>
con's avatar
con committed
55
#include <coreplugin/modemanager.h>
hjk's avatar
hjk committed
56
57
58
#include <coreplugin/navigationwidget.h>
#include <coreplugin/outputpane.h>
#include <coreplugin/rightpane.h>
con's avatar
con committed
59
#include <coreplugin/uniqueidmanager.h>
hjk's avatar
hjk committed
60

con's avatar
con committed
61
#include <cplusplus/ExpressionUnderCursor.h>
hjk's avatar
hjk committed
62

con's avatar
con committed
63
#include <cppeditor/cppeditorconstants.h>
hjk's avatar
hjk committed
64

65
66
#include <extensionsystem/pluginmanager.h>

67
#include <coreplugin/manhattanstyle.h>
68
#include <projectexplorer/projectexplorer.h>
con's avatar
con committed
69
70
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/session.h>
71
#include <projectexplorer/project.h>
hjk's avatar
hjk committed
72
73

#include <texteditor/basetexteditor.h>
con's avatar
con committed
74
75
76
#include <texteditor/basetextmark.h>
#include <texteditor/itexteditor.h>
#include <texteditor/texteditorconstants.h>
77
#include <texteditor/texteditorplugin.h>
hjk's avatar
hjk committed
78
79

#include <utils/qtcassert.h>
80
#include <utils/styledbar.h>
con's avatar
con committed
81
82
83
84
85

#include <QtCore/QDebug>
#include <QtCore/QObject>
#include <QtCore/QPoint>
#include <QtCore/QSettings>
86
#include <QtCore/QtPlugin>
87
#include <QtCore/QCoreApplication>
88
#include <QtCore/QTimer>
89
#include <QtCore/QVariant>
hjk's avatar
hjk committed
90

91
#include <QtGui/QLineEdit>
92
#include <QtGui/QDockWidget>
con's avatar
con committed
93
94
95
#include <QtGui/QPlainTextEdit>
#include <QtGui/QTextBlock>
#include <QtGui/QTextCursor>
96
#include <QtGui/QToolButton>
97
#include <QtGui/QMessageBox>
con's avatar
con committed
98

99
100
#include <climits>

con's avatar
con committed
101
using namespace Core;
102
using namespace Debugger;
hjk's avatar
hjk committed
103
104
using namespace Debugger::Constants;
using namespace Debugger::Internal;
con's avatar
con committed
105
using namespace ProjectExplorer;
hjk's avatar
hjk committed
106
using namespace TextEditor;
con's avatar
con committed
107
108
109
110
111


namespace Debugger {
namespace Constants {

112
113
const char * const M_DEBUG_START_DEBUGGING = "QtCreator.Menu.Debug.StartDebugging";

con's avatar
con committed
114
115
const char * const STARTEXTERNAL        = "Debugger.StartExternal";
const char * const ATTACHEXTERNAL       = "Debugger.AttachExternal";
116
const char * const ATTACHCORE           = "Debugger.AttachCore";
117
const char * const ATTACHREMOTE         = "Debugger.AttachRemote";
118
const char * const DETACH               = "Debugger.Detach";
con's avatar
con committed
119

120
121
const char * const RUN_TO_LINE1         = "Debugger.RunToLine1";
const char * const RUN_TO_LINE2         = "Debugger.RunToLine2";
con's avatar
con committed
122
const char * const RUN_TO_FUNCTION      = "Debugger.RunToFunction";
123
124
const char * const JUMP_TO_LINE1        = "Debugger.JumpToLine1";
const char * const JUMP_TO_LINE2        = "Debugger.JumpToLine2";
125
const char * const RETURN_FROM_FUNCTION = "Debugger.ReturnFromFunction";
126
const char * const SNAPSHOT             = "Debugger.Snapshot";
con's avatar
con committed
127
128
129
const char * const TOGGLE_BREAK         = "Debugger.ToggleBreak";
const char * const BREAK_BY_FUNCTION    = "Debugger.BreakByFunction";
const char * const BREAK_AT_MAIN        = "Debugger.BreakAtMain";
130
131
const char * const ADD_TO_WATCH1        = "Debugger.AddToWatch1";
const char * const ADD_TO_WATCH2        = "Debugger.AddToWatch2";
132
const char * const OPERATE_BY_INSTRUCTION  = "Debugger.OperateByInstruction";
con's avatar
con committed
133

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
134
#ifdef Q_WS_MAC
con's avatar
con committed
135
136
137
138
139
const char * const INTERRUPT_KEY            = "Shift+F5";
const char * const RESET_KEY                = "Ctrl+Shift+F5";
const char * const STEP_KEY                 = "F7";
const char * const STEPOUT_KEY              = "Shift+F7";
const char * const NEXT_KEY                 = "F6";
140
const char * const REVERSE_KEY              = "";
con's avatar
con committed
141
142
143
144
145
146
147
const char * const RUN_TO_LINE_KEY          = "Shift+F8";
const char * const RUN_TO_FUNCTION_KEY      = "Ctrl+F6";
const char * const JUMP_TO_LINE_KEY         = "Alt+D,Alt+L";
const char * const TOGGLE_BREAK_KEY         = "F8";
const char * const BREAK_BY_FUNCTION_KEY    = "Alt+D,Alt+F";
const char * const BREAK_AT_MAIN_KEY        = "Alt+D,Alt+M";
const char * const ADD_TO_WATCH_KEY         = "Alt+D,Alt+W";
148
const char * const SNAPSHOT_KEY             = "Alt+D,Alt+S";
con's avatar
con committed
149
150
151
152
153
154
#else
const char * const INTERRUPT_KEY            = "Shift+F5";
const char * const RESET_KEY                = "Ctrl+Shift+F5";
const char * const STEP_KEY                 = "F11";
const char * const STEPOUT_KEY              = "Shift+F11";
const char * const NEXT_KEY                 = "F10";
155
const char * const REVERSE_KEY              = "F12";
con's avatar
con committed
156
157
158
159
160
161
162
const char * const RUN_TO_LINE_KEY          = "";
const char * const RUN_TO_FUNCTION_KEY      = "";
const char * const JUMP_TO_LINE_KEY         = "";
const char * const TOGGLE_BREAK_KEY         = "F9";
const char * const BREAK_BY_FUNCTION_KEY    = "";
const char * const BREAK_AT_MAIN_KEY        = "";
const char * const ADD_TO_WATCH_KEY         = "Ctrl+Alt+Q";
163
const char * const SNAPSHOT_KEY             = "Alt+D,Alt+S";
con's avatar
con committed
164
165
166
167
168
169
#endif

} // namespace Constants
} // namespace Debugger


170
171
172
173
174
static ProjectExplorer::SessionManager *sessionManager()
{
    return ProjectExplorer::ProjectExplorerPlugin::instance()->session();
}

175
176
177
178
179
static QSettings *settings()
{
    return ICore::instance()->settings();
}

180
181
182
183
184
185
186
static QToolButton *toolButton(QAction *action)
{
    QToolButton *button = new QToolButton;
    button->setDefaultAction(action);
    return button;
}

187
188
189
190
191
192
///////////////////////////////////////////////////////////////////////
//
// DebugMode
//
///////////////////////////////////////////////////////////////////////

hjk's avatar
hjk committed
193
194
195
196
197
198
199
200
201
202
203
204
205
namespace Debugger {
namespace Internal {

class DebugMode : public Core::BaseMode
{
    Q_OBJECT

public:
    DebugMode(QObject *parent = 0);
    ~DebugMode();
};

DebugMode::DebugMode(QObject *parent)
hjk's avatar
hjk committed
206
  : BaseMode(parent)
hjk's avatar
hjk committed
207
{
208
209
    setDisplayName(tr("Debug"));
    setId(Constants::MODE_DEBUG);
hjk's avatar
hjk committed
210
211
    setIcon(QIcon(":/fancyactionbar/images/mode_Debug.png"));
    setPriority(Constants::P_MODE_DEBUG);
hjk's avatar
hjk committed
212
213
214
215
216
217
218
219
}

DebugMode::~DebugMode()
{
    // Make sure the editor manager does not get deleted
    EditorManager::instance()->setParent(0);
}

220
221
222
223
224
225
///////////////////////////////////////////////////////////////////////
//
// DebuggerListener: Close the debugging session if running.
//
///////////////////////////////////////////////////////////////////////

226
227
class DebuggerListener : public Core::ICoreListener
{
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
    Q_OBJECT
public:
    explicit DebuggerListener(QObject *parent = 0);
    virtual bool coreAboutToClose();
};

DebuggerListener::DebuggerListener(QObject *parent) :
    Core::ICoreListener(parent)
{
}

bool DebuggerListener::coreAboutToClose()
{
    DebuggerManager *mgr = DebuggerManager::instance();
    if (!mgr)
        return true;
    // Ask to terminate the session.
    const QString title = tr("Close Debugging Session");
    bool cleanTermination = false;
    switch (mgr->state()) {
    case DebuggerNotReady:
        return true;
    case AdapterStarted:     // Most importantly, terminating a running
    case AdapterStartFailed: // debuggee can cause problems.
    case InferiorUnrunnable:
    case InferiorStartFailed:
    case InferiorStopped:
    case InferiorShutDown:
        cleanTermination = true;
        break;
    default:
        break;
    }
    const QString question = cleanTermination ?
262
        tr("A debugging session is still in progress.\nWould you like to terminate it?") :
263
264
        tr("A debugging session is still in progress. Terminating the session in the current"
           " state (%1) can leave the target in an inconsistent state."
265
           " Would you still like to terminate it?")
266
        .arg(QLatin1String(DebuggerManager::stateName(mgr->state())));
267
268
    QMessageBox::StandardButton answer = QMessageBox::question(DebuggerUISwitcher::instance()->mainWindow(),
                                         title, question,
269
270
                                         QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes);
    if (answer != QMessageBox::Yes)
271
272
        return false;
    mgr->exitDebugger();
273
    QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
274
275
276
    return true;
}

277
278
279
} // namespace Internal
} // namespace Debugger

hjk's avatar
hjk committed
280

con's avatar
con committed
281
282
283
284
285
286
///////////////////////////////////////////////////////////////////////
//
// LocationMark
//
///////////////////////////////////////////////////////////////////////

287
288
289
namespace Debugger {
namespace Internal {

290
// Used in "real" editors
291
class LocationMark : public TextEditor::BaseTextMark
con's avatar
con committed
292
293
294
295
296
297
{
    Q_OBJECT

public:
    LocationMark(const QString &fileName, int linenumber)
        : BaseTextMark(fileName, linenumber)
298
    {}
con's avatar
con committed
299

300
    QIcon icon() const { return DebuggerManager::instance()->locationMarkIcon(); }
con's avatar
con committed
301
302
    void updateLineNumber(int /*lineNumber*/) {}
    void updateBlock(const QTextBlock & /*block*/) {}
303
    void removedFromEditor() {}
con's avatar
con committed
304
305
};

306
307
308
309
310
311
} // namespace Internal
} // namespace Debugger


///////////////////////////////////////////////////////////////////////
//
312
// CommonOptionsPage
313
314
315
316
317
318
//
///////////////////////////////////////////////////////////////////////

namespace Debugger {
namespace Internal {

319
class CommonOptionsPage : public Core::IOptionsPage
320
321
322
323
{
    Q_OBJECT

public:
324
    CommonOptionsPage() {}
325
326

    // IOptionsPage
327
    QString id() const
328
        { return QLatin1String(Debugger::Constants::DEBUGGER_COMMON_SETTINGS_ID); }
329
    QString displayName() const
330
        { return QCoreApplication::translate("Debugger", Debugger::Constants::DEBUGGER_COMMON_SETTINGS_NAME); }
331
332
    QString category() const
        { return QLatin1String(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY);  }
333
    QString displayCategory() const
334
        { return QCoreApplication::translate("Debugger", Debugger::Constants::DEBUGGER_SETTINGS_TR_CATEGORY); }
335
336

    QWidget *createPage(QWidget *parent);
337
    void apply() { m_group.apply(settings()); }
338
    void finish() { m_group.finish(); }
339
    virtual bool matches(const QString &s) const;
340
341

private:
342
    Ui::CommonOptionsPage m_ui;
343
    Utils::SavedActionSet m_group;
344
    QString m_searchKeywords;
345
346
};

347
QWidget *CommonOptionsPage::createPage(QWidget *parent)
348
349
350
{
    QWidget *w = new QWidget(parent);
    m_ui.setupUi(w);
351
    m_group.clear();
352

353
    m_group.insert(theDebuggerAction(ListSourceFiles),
354
        m_ui.checkBoxListSourceFiles);
355
    m_group.insert(theDebuggerAction(UseAlternatingRowColors),
356
        m_ui.checkBoxUseAlternatingRowColors);
357
358
    m_group.insert(theDebuggerAction(UseMessageBoxForSignals),
        m_ui.checkBoxUseMessageBoxForSignals);
359
    m_group.insert(theDebuggerAction(SkipKnownFrames),
360
        m_ui.checkBoxSkipKnownFrames);
361
    m_group.insert(theDebuggerAction(UseToolTipsInMainEditor),
362
        m_ui.checkBoxUseToolTipsInMainEditor);
363
    m_group.insert(theDebuggerAction(AutoDerefPointers), 0);
364
365
366
367
    m_group.insert(theDebuggerAction(UseToolTipsInLocalsView), 0);
    m_group.insert(theDebuggerAction(UseToolTipsInBreakpointsView), 0);
    m_group.insert(theDebuggerAction(UseAddressInBreakpointsView), 0);
    m_group.insert(theDebuggerAction(UseAddressInStackView), 0);
368
    m_group.insert(theDebuggerAction(EnableReverseDebugging),
369
        m_ui.checkBoxEnableReverseDebugging);
370
    m_group.insert(theDebuggerAction(MaximalStackDepth),
371
        m_ui.spinBoxMaximalStackDepth);
372
    m_group.insert(theDebuggerAction(GdbWatchdogTimeout), 0);
373
374
    m_group.insert(theDebuggerAction(ShowStdNamespace), 0);
    m_group.insert(theDebuggerAction(ShowQtNamespace), 0);
375
    m_group.insert(theDebuggerAction(LogTimeStamps), 0);
376
    m_group.insert(theDebuggerAction(VerboseLog), 0);
377
    m_group.insert(theDebuggerAction(UsePreciseBreakpoints), 0);
378
379
    m_group.insert(theDebuggerAction(BreakOnThrow), 0);
    m_group.insert(theDebuggerAction(BreakOnCatch), 0);
380

381
382
383
384
385
386
387
388
389
390
391
    if (m_searchKeywords.isEmpty()) {
        QTextStream(&m_searchKeywords) << ' ' << m_ui.checkBoxListSourceFiles->text()
                << ' ' << m_ui.checkBoxUseMessageBoxForSignals->text()
                << ' ' << m_ui.checkBoxUseAlternatingRowColors->text()
                << ' ' << m_ui.checkBoxUseToolTipsInMainEditor->text()
                << ' ' << m_ui.checkBoxSkipKnownFrames->text()
                << ' ' << m_ui.checkBoxEnableReverseDebugging->text()
                << ' ' << m_ui.labelMaximalStackDepth->text();
        m_searchKeywords.remove(QLatin1Char('&'));
    }

392
393
394
    return w;
}

395
396
397
398
399
bool CommonOptionsPage::matches(const QString &s) const
{
    return m_searchKeywords.contains(s, Qt::CaseInsensitive);
}

400
401
402
} // namespace Internal
} // namespace Debugger

hjk's avatar
hjk committed
403

hjk's avatar
hjk committed
404
405
///////////////////////////////////////////////////////////////////////
//
406
// DebuggingHelperOptionPage
hjk's avatar
hjk committed
407
408
409
//
///////////////////////////////////////////////////////////////////////

410
411
412
static inline bool oxygenStyle()
{
    if (const ManhattanStyle *ms = qobject_cast<const ManhattanStyle *>(qApp->style()))
413
        return !qstrcmp("OxygenStyle", ms->baseStyle()->metaObject()->className());
414
415
416
    return false;
}

hjk's avatar
hjk committed
417
418
419
namespace Debugger {
namespace Internal {

420
class DebuggingHelperOptionPage : public Core::IOptionsPage
hjk's avatar
hjk committed
421
422
423
424
{
    Q_OBJECT

public:
425
    DebuggingHelperOptionPage() {}
hjk's avatar
hjk committed
426
427

    // IOptionsPage
428
    QString id() const { return QLatin1String("B.DebuggingHelper"); }
429
    QString displayName() const { return tr("Debugging Helper"); }
430
    QString category() const { return QLatin1String(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY); }
431
    QString displayCategory() const { return QCoreApplication::translate("Debugger", Debugger::Constants::DEBUGGER_SETTINGS_TR_CATEGORY); }
hjk's avatar
hjk committed
432
433

    QWidget *createPage(QWidget *parent);
434
    void apply() { m_group.apply(settings()); }
435
    void finish() { m_group.finish(); }
436
    virtual bool matches(const QString &s) const;
hjk's avatar
hjk committed
437
438

private:
439
    Ui::DebuggingHelperOptionPage m_ui;
440
    Utils::SavedActionSet m_group;
441
    QString m_searchKeywords;
hjk's avatar
hjk committed
442
443
};

444
QWidget *DebuggingHelperOptionPage::createPage(QWidget *parent)
hjk's avatar
hjk committed
445
446
447
448
{
    QWidget *w = new QWidget(parent);
    m_ui.setupUi(w);

449
    m_ui.dumperLocationChooser->setExpectedKind(Utils::PathChooser::Command);
450
    m_ui.dumperLocationChooser->setPromptDialogTitle(tr("Choose DebuggingHelper Location"));
hjk's avatar
hjk committed
451
452
    m_ui.dumperLocationChooser->setInitialBrowsePathBackup(
        Core::ICore::instance()->resourcePath() + "../../lib");
hjk's avatar
hjk committed
453

454
    m_group.clear();
455
    m_group.insert(theDebuggerAction(UseDebuggingHelpers),
456
        m_ui.debuggingHelperGroupBox);
457
    m_group.insert(theDebuggerAction(UseCustomDebuggingHelperLocation),
458
459
460
461
462
        m_ui.customLocationGroupBox);
    // Suppress Oxygen style's giving flat group boxes bold titles
    if (oxygenStyle())
        m_ui.customLocationGroupBox->setStyleSheet(QLatin1String("QGroupBox::title { font: ; }"));

463
    m_group.insert(theDebuggerAction(CustomDebuggingHelperLocation),
464
        m_ui.dumperLocationChooser);
hjk's avatar
hjk committed
465

466
467
468
    m_group.insert(theDebuggerAction(UseCodeModel),
        m_ui.checkBoxUseCodeModel);

469
#ifdef QT_DEBUG
470
471
    m_group.insert(theDebuggerAction(DebugDebuggingHelpers),
        m_ui.checkBoxDebugDebuggingHelpers);
472
473
474
#else
    m_ui.checkBoxDebugDebuggingHelpers->hide();
#endif
hjk's avatar
hjk committed
475
476
477
478
479
480
481
482
483
484
485

#ifndef QT_DEBUG
#if 0
    cmd = am->registerAction(m_manager->m_dumpLogAction,
        Constants::DUMP_LOG, globalcontext);
    //cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+D,Ctrl+L")));
    cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+F11")));
    mdebug->addAction(cmd);
#endif
#endif

486
487
488
489
490
491
492
493
494
    if (m_searchKeywords.isEmpty()) {
        QTextStream(&m_searchKeywords)
                << ' ' << m_ui.debuggingHelperGroupBox->title()
                << ' ' << m_ui.customLocationGroupBox->title()
                << ' ' << m_ui.dumperLocationLabel->text()
                << ' ' << m_ui.checkBoxUseCodeModel->text()
                << ' ' << m_ui.checkBoxDebugDebuggingHelpers->text();
        m_searchKeywords.remove(QLatin1Char('&'));
    }
hjk's avatar
hjk committed
495
496
497
    return w;
}

498
bool DebuggingHelperOptionPage::matches(const QString &s) const
hjk's avatar
hjk committed
499
{
500
    return m_searchKeywords.contains(s, Qt::CaseInsensitive);
hjk's avatar
hjk committed
501
502
}

hjk's avatar
hjk committed
503
504
505
} // namespace Internal
} // namespace Debugger

506

con's avatar
con committed
507
508
509
510
511
512
///////////////////////////////////////////////////////////////////////
//
// DebuggerPlugin
//
///////////////////////////////////////////////////////////////////////

513
514
515
516
517
518
519

DebuggerPlugin::AttachRemoteParameters::AttachRemoteParameters() :
    attachPid(0),
    winCrashEvent(0)
{
}

520
521
DebuggerPlugin::DebuggerPlugin()
  : m_manager(0),
522
523
524
    m_debugMode(0),
    m_locationMark(0),
    m_gdbRunningContext(0),
525
    m_cmdLineEnabledEngines(AllEngineTypes)
526
{}
con's avatar
con committed
527
528
529
530
531
532

DebuggerPlugin::~DebuggerPlugin()
{}

void DebuggerPlugin::shutdown()
{
hjk's avatar
hjk committed
533
    QTC_ASSERT(m_manager, /**/);
con's avatar
con committed
534
535
536
    if (m_manager)
        m_manager->shutdown();

hjk's avatar
hjk committed
537
    writeSettings();
538
539
540
541

    if (m_uiSwitcher)
        m_uiSwitcher->shutdown();

dt's avatar
dt committed
542
    delete DebuggerSettings::instance();
hjk's avatar
hjk committed
543

con's avatar
con committed
544
545
546
547
548
549
550
551
552
553
    removeObject(m_debugMode);

    // FIXME: when using the line below, BreakWindow etc gets deleted twice.
    // so better leak for now...
    delete m_debugMode;
    m_debugMode = 0;

    delete m_locationMark;
    m_locationMark = 0;

ck's avatar
ck committed
554
    removeObject(m_manager);
con's avatar
con committed
555
556
    delete m_manager;
    m_manager = 0;
557
558
559
560

    removeObject(m_uiSwitcher);
    delete m_uiSwitcher;
    m_uiSwitcher = 0;
con's avatar
con committed
561
562
}

563
static QString msgParameterMissing(const QString &a)
564
565
566
567
{
    return DebuggerPlugin::tr("Option '%1' is missing the parameter.").arg(a);
}

568
static QString msgInvalidNumericParameter(const QString &a, const QString &number)
569
570
571
572
573
{
    return DebuggerPlugin::tr("The parameter '%1' of option '%2' is not a number.").arg(number, a);
}

// Parse arguments
574
575
576
577
static bool parseArgument(QStringList::const_iterator &it,
                          const QStringList::const_iterator &cend,
                          DebuggerPlugin::AttachRemoteParameters *attachRemoteParameters,
                          unsigned *enabledEngines, QString *errorMessage)
578
579
580
581
582
583
584
585
586
587
{
    const QString &option = *it;
    // '-debug <pid>'
    if (*it == QLatin1String("-debug")) {
        ++it;
        if (it == cend) {
            *errorMessage = msgParameterMissing(*it);
            return false;
        }
        bool ok;
588
        attachRemoteParameters->attachPid = it->toULongLong(&ok);
589
        if (!ok) {
590
591
            attachRemoteParameters->attachPid = 0;
            attachRemoteParameters->attachCore = *it;
592
593
594
        }
        return true;
    }
595
596
597
    // -wincrashevent <event-handle>. A handle used for
    // a handshake when attaching to a crashed Windows process.
    if (*it == QLatin1String("-wincrashevent")) {
598
599
600
601
602
603
        ++it;
        if (it == cend) {
            *errorMessage = msgParameterMissing(*it);
            return false;
        }
        bool ok;
604
        attachRemoteParameters->winCrashEvent = it->toULongLong(&ok);
605
606
607
608
609
610
611
612
        if (!ok) {
            *errorMessage = msgInvalidNumericParameter(option, *it);
            return false;
        }
        return true;
    }
    // engine disabling
    if (option == QLatin1String("-disable-cdb")) {
613
        *enabledEngines &= ~Debugger::CdbEngineType;
614
615
616
        return true;
    }
    if (option == QLatin1String("-disable-gdb")) {
617
        *enabledEngines &= ~Debugger::GdbEngineType;
618
619
620
        return true;
    }
    if (option == QLatin1String("-disable-sdb")) {
621
        *enabledEngines &= ~Debugger::ScriptEngineType;
622
623
624
        return true;
    }

625
    *errorMessage = DebuggerPlugin::tr("Invalid debugger option: %1").arg(option);
626
627
628
    return false;
}

629
630
631
static bool parseArguments(const QStringList &args,
                           DebuggerPlugin::AttachRemoteParameters *attachRemoteParameters,
                           unsigned *enabledEngines, QString *errorMessage)
632
633
634
{
    const QStringList::const_iterator cend = args.constEnd();
    for (QStringList::const_iterator it = args.constBegin(); it != cend; ++it)
635
        if (!parseArgument(it, cend, attachRemoteParameters, enabledEngines, errorMessage))
636
637
            return false;
    if (Debugger::Constants::Internal::debug)
638
        qDebug().nospace() << args << "engines=0x"
639
640
641
            << QString::number(*enabledEngines, 16)
            << " pid" << attachRemoteParameters->attachPid
            << " core" << attachRemoteParameters->attachCore << '\n';
642
643
644
    return true;
}

645
646
647
648
649
650
651
652
653
654
655
656
657
void DebuggerPlugin::remoteCommand(const QStringList &options, const QStringList &)
{
    QString errorMessage;
    AttachRemoteParameters parameters;
    unsigned dummy = 0;
    // Did we receive a request for debugging (unless it is ourselves)?
    if (parseArguments(options, &parameters, &dummy, &errorMessage)
        && parameters.attachPid != quint64(QCoreApplication::applicationPid())) {
        m_attachRemoteParameters = parameters;
        attachCmdLine();
    }
}

hjk's avatar
hjk committed
658
bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMessage)
con's avatar
con committed
659
{
660
    // Do not fail the whole plugin if something goes wrong here
661
    if (!parseArguments(arguments, &m_attachRemoteParameters, &m_cmdLineEnabledEngines, errorMessage)) {
662
663
        *errorMessage = tr("Error evaluating command line arguments: %1")
            .arg(*errorMessage);
664
665
666
        qWarning("%s\n", qPrintable(*errorMessage));
        errorMessage->clear();
    }
con's avatar
con committed
667

668
669
670
671
672
673
674
    // Debug mode setup
    m_debugMode = new DebugMode(this);
    //addAutoReleasedObject(m_debugMode);
    m_uiSwitcher = new DebuggerUISwitcher(m_debugMode, this);
    ExtensionSystem::PluginManager::instance()->addObject(m_uiSwitcher);
    m_uiSwitcher->addLanguage(LANG_CPP);

675
    ICore *core = ICore::instance();
hjk's avatar
hjk committed
676
    QTC_ASSERT(core, return false);
con's avatar
con committed
677

678
679
    Core::ActionManager *am = core->actionManager();
    QTC_ASSERT(am, return false);
con's avatar
con committed
680
681

    Core::UniqueIDManager *uidm = core->uniqueIDManager();
hjk's avatar
hjk committed
682
    QTC_ASSERT(uidm, return false);
con's avatar
con committed
683
684
685
686
687
688
689
690
691
692
693

    QList<int> globalcontext;
    globalcontext << Core::Constants::C_GLOBAL_ID;

    QList<int> cppcontext;
    cppcontext << uidm->uniqueIdentifier(ProjectExplorer::Constants::LANG_CXX);

    QList<int> debuggercontext;
    debuggercontext << uidm->uniqueIdentifier(C_GDBDEBUGGER);

    QList<int> cppeditorcontext;
694
    cppeditorcontext << uidm->uniqueIdentifier(CppEditor::Constants::C_CPPEDITOR);
con's avatar
con committed
695
696
697
698
699
700

    QList<int> texteditorcontext;
    texteditorcontext << uidm->uniqueIdentifier(TextEditor::Constants::C_TEXTEDITOR);

    m_gdbRunningContext = uidm->uniqueIdentifier(Constants::GDBRUNNING);

701
702
703
704
705
    DebuggerManager *manager = new DebuggerManager(this);
    ExtensionSystem::PluginManager::instance()->addObject(manager);
    const QList<Core::IOptionsPage *> engineOptionPages =
        manager->initializeEngines(m_cmdLineEnabledEngines);

706
    // Register factory of DebuggerRunControl.
707
    m_debuggerRunControlFactory = new DebuggerRunControlFactory(manager);
708
709
710
711
712
713
714
715
    addAutoReleasedObject(m_debuggerRunControlFactory);

    QList<int> context;
    context.append(uidm->uniqueIdentifier(Core::Constants::C_EDITORMANAGER));
    context.append(uidm->uniqueIdentifier(Debugger::Constants::C_GDBDEBUGGER));
    context.append(uidm->uniqueIdentifier(Core::Constants::C_NAVIGATION_PANE));
    m_debugMode->setContext(context);

716
    m_reverseToolButton = 0;
con's avatar
con committed
717

718
    // Handling of external applications.
719
720
721
722
723
724
725
726
727
728
729
730
731
732
    m_startExternalAction = new QAction(this);
    m_startExternalAction->setText(tr("Start and Debug External Application..."));
    connect(m_startExternalAction, SIGNAL(triggered()),
        this, SLOT(startExternalApplication()));

    m_attachExternalAction = new QAction(this);
    m_attachExternalAction->setText(tr("Attach to Running External Application..."));
    connect(m_attachExternalAction, SIGNAL(triggered()),
        this, SLOT(attachExternalApplication()));

    m_attachCoreAction = new QAction(this);
    m_attachCoreAction->setText(tr("Attach to Core..."));
    connect(m_attachCoreAction, SIGNAL(triggered()), this, SLOT(attachCore()));

733
734
735
736
    m_startRemoteAction = new QAction(this);
    m_startRemoteAction->setText(tr("Start and Attach to Remote Application..."));
    connect(m_startRemoteAction, SIGNAL(triggered()),
        this, SLOT(startRemoteApplication()));
737

738
    m_detachAction = new QAction(this);
739
    m_detachAction->setText(tr("Detach Debugger"));
740
    connect(m_detachAction, SIGNAL(triggered()),
741
        manager, SLOT(detachDebugger()));
742

743
    Core::Command *cmd = 0;
744
    const DebuggerManagerActions actions = manager->debuggerManagerActions();
745

746
747
748
    Core::ActionContainer *mstart =
        am->actionContainer(ProjectExplorer::Constants::M_DEBUG_STARTDEBUGGING);

749
    cmd = am->registerAction(actions.continueAction,
750
        ProjectExplorer::Constants::DEBUG, QList<int>() << m_gdbRunningContext);
751
    mstart->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
752

753
    cmd = am->registerAction(m_startExternalAction,
con's avatar
con committed
754
        Constants::STARTEXTERNAL, globalcontext);
755
    mstart->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
con's avatar
con committed
756

757
    cmd = am->registerAction(m_attachExternalAction,
con's avatar
con committed
758
        Constants::ATTACHEXTERNAL, globalcontext);
759
    mstart->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
760

761
762
    cmd = am->registerAction(m_attachCoreAction,
        Constants::ATTACHCORE, globalcontext);
763
    mstart->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
764

765
    cmd = am->registerAction(m_startRemoteAction,
766
        Constants::ATTACHREMOTE, globalcontext);
767
    mstart->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
768

769
770
    cmd = am->registerAction(m_detachAction,
        Constants::DETACH, globalcontext);
771
    m_uiSwitcher->addMenuAction(cmd, Core::Constants::G_DEFAULT_ONE);
con's avatar
con committed
772

773
    cmd = am->registerAction(actions.stopAction,
con's avatar
con committed
774
        Constants::INTERRUPT, globalcontext);
con's avatar
con committed
775
776
    cmd->setAttribute(Core::Command::CA_UpdateText);
    cmd->setAttribute(Core::Command::CA_UpdateIcon);
con's avatar
con committed
777
778
    cmd->setDefaultKeySequence(QKeySequence(Constants::INTERRUPT_KEY));
    cmd->setDefaultText(tr("Stop Debugger/Interrupt Debugger"));
779
    m_uiSwitcher->addMenuAction(cmd, Core::Constants::G_DEFAULT_ONE);
con's avatar
con committed
780

781
    cmd = am->registerAction(actions.resetAction,
con's avatar
con committed
782
        Constants::RESET, globalcontext);
con's avatar
con committed
783
    cmd->setAttribute(Core::Command::CA_UpdateText);
784
    //cmd->setDefaultKeySequence(QKeySequence(Constants::RESET_KEY));
con's avatar
con committed
785
    cmd->setDefaultText(tr("Reset Debugger"));
786
    m_uiSwitcher->addMenuAction(cmd, Core::Constants::G_DEFAULT_ONE);
con's avatar
con committed
787
788
789

    QAction *sep = new QAction(this);
    sep->setSeparator(true);
con's avatar
con committed
790
    cmd = am->registerAction(sep, QLatin1String("Debugger.Sep.Step"), globalcontext);
791
    m_uiSwitcher->addMenuAction(cmd);
con's avatar
con committed
792

793
    cmd = am->registerAction(actions.nextAction,
con's avatar
con committed
794
795
        Constants::NEXT, debuggercontext);
    cmd->setDefaultKeySequence(QKeySequence(Constants::NEXT_KEY));
796
    m_uiSwitcher->addMenuAction(cmd);
con's avatar
con committed
797

798
    cmd = am->registerAction(actions.stepAction,
con's avatar
con committed
799
800
        Constants::STEP, debuggercontext);
    cmd->setDefaultKeySequence(QKeySequence(Constants::STEP_KEY));
801
    m_uiSwitcher->addMenuAction(cmd);
con's avatar
con committed
802

803
    cmd = am->registerAction(actions.stepOutAction,
con's avatar
con committed
804
805
        Constants::STEPOUT, debuggercontext);
    cmd->setDefaultKeySequence(QKeySequence(Constants::STEPOUT_KEY));
806
    m_uiSwitcher->addMenuAction(cmd);
con's avatar
con committed
807

808
809
    cmd = am->registerAction(actions.runToLineAction1,
        Constants::RUN_TO_LINE1, debuggercontext);
con's avatar
con committed
810
    cmd->setDefaultKeySequence(QKeySequence(Constants::RUN_TO_LINE_KEY));
811
    m_uiSwitcher->addMenuAction(cmd);
con's avatar
con committed
812

813
    cmd = am->registerAction(actions.runToFunctionAction,
con's avatar
con committed
814
815
        Constants::RUN_TO_FUNCTION, debuggercontext);
    cmd->setDefaultKeySequence(QKeySequence(Constants::RUN_TO_FUNCTION_KEY));
816
    m_uiSwitcher->addMenuAction(cmd);
con's avatar
con committed
817

818
819
    cmd = am->registerAction(actions.jumpToLineAction1,
        Constants::JUMP_TO_LINE1, debuggercontext);
820
    m_uiSwitcher->addMenuAction(cmd);
con's avatar
con committed
821

822
823
    cmd = am->registerAction(actions.returnFromFunctionAction,
        Constants::RETURN_FROM_FUNCTION, debuggercontext);
824
    m_uiSwitcher->addMenuAction(cmd);
825

826
    cmd = am->registerAction(actions.reverseDirectionAction,
827
828
        Constants::REVERSE, debuggercontext);
    cmd->setDefaultKeySequence(QKeySequence(Constants::REVERSE_KEY));
829
    m_uiSwitcher->addMenuAction(cmd);
830

con's avatar
con committed
831
832
    sep = new QAction(this);
    sep->setSeparator(true);
con's avatar
con committed
833
    cmd = am->registerAction(sep, QLatin1String("Debugger.Sep.Break"), globalcontext);
834
    m_uiSwitcher->addMenuAction(cmd);
con's avatar
con committed
835

836
837
838
    cmd = am->registerAction(actions.snapshotAction,
        Constants::SNAPSHOT, debuggercontext);
    cmd->setDefaultKeySequence(QKeySequence(Constants::SNAPSHOT_KEY));
839
    m_uiSwitcher->addMenuAction(cmd);
840

841
842
    cmd = am->registerAction(theDebuggerAction(OperateByInstruction),
        Constants::OPERATE_BY_INSTRUCTION, debuggercontext);
843
    m_uiSwitcher->addMenuAction(cmd);
844

845
    cmd = am->registerAction(actions.breakAction,
con's avatar
con committed
846
847
        Constants::TOGGLE_BREAK, cppeditorcontext);
    cmd->setDefaultKeySequence(QKeySequence(Constants::TOGGLE_BREAK_KEY));
848
    m_uiSwitcher->addMenuAction(cmd);
con's avatar
con committed
849
850
851
852
    //mcppcontext->addAction(cmd);

    sep = new QAction(this);
    sep->setSeparator(true);
con's avatar
con committed
853
    cmd = am->registerAction(sep, QLatin1String("Debugger.Sep.Watch"), globalcontext);
854
    m_uiSwitcher->addMenuAction(cmd);
con's avatar
con committed
855

856
857
    cmd = am->registerAction(actions.watchAction1,
        Constants::ADD_TO_WATCH1, cppeditorcontext);
858
    cmd->action()->setEnabled(true);
859
    //cmd->setDefaultKeySequence(QKeySequence(tr("ALT+D,ALT+W")));
860
    m_uiSwitcher->addMenuAction(cmd);
861

862
    // Editor context menu
863
864
865
866
867
868
    ActionContainer *editorContextMenu =
        am->actionContainer(CppEditor::Constants::M_CONTEXT);
    cmd = am->registerAction(sep, QLatin1String("Debugger.Sep.Views"),
        debuggercontext);
    editorContextMenu->addAction(cmd);
    cmd->setAttribute(Command::CA_Hide);
869

870
871
872
    cmd = am->registerAction(actions.watchAction2,
        Constants::ADD_TO_WATCH2, debuggercontext);
    cmd->action()->setEnabled(true);
873
874
875
876
877
878
879
880
881
882
883
884
    editorContextMenu->addAction(cmd);
    cmd->setAttribute(Command::CA_Hide);

    cmd = am->registerAction(actions.runToLineAction2,
        Constants::RUN_TO_LINE2, debuggercontext);
    cmd->action()->setEnabled(true);
    editorContextMenu->addAction(cmd);
    cmd->setAttribute(Command::CA_Hide);

    cmd = am->registerAction(actions.jumpToLineAction2,
        Constants::JUMP_TO_LINE2, debuggercontext);
    cmd->action()->setEnabled(true);
885
886
    editorContextMenu->addAction(cmd);
    cmd->setAttribute(Command::CA_Hide);
con's avatar
con committed
887

hjk's avatar
hjk committed
888
    // FIXME:
889
    addAutoReleasedObject(new CommonOptionsPage);
890
    addAutoReleasedObject(new DebuggingHelperOptionPage);
891
892
    foreach (Core::IOptionsPage* op, engineOptionPages)
        addAutoReleasedObject(op);
893
    addAutoReleasedObject(new DebuggerListener);
con's avatar
con committed
894
895
    m_locationMark = 0;

896
    manager->setSimpleDockWidgetArrangement(LANG_CPP);
hjk's avatar
hjk committed
897
898
899
    readSettings();

    connect(ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*)),
900
            this, SLOT(onModeChanged(Core::IMode*)));
hjk's avatar
hjk committed
901
902
903
    m_debugMode->widget()->setFocusProxy(EditorManager::instance());
    addObject(m_debugMode);

904
905
906
    m_manager = manager;


hjk's avatar
hjk committed
907
908
909
910
    //
    //  Connections
    //

911
    // TextEditor
912
    connect(TextEditorPlugin::instance(),
913
        SIGNAL(fontSettingsChanged(TextEditor::FontSettings)),
914
        manager, SLOT(fontSettingsChanged(TextEditor::FontSettings)));
915

con's avatar
con committed
916
    // ProjectExplorer
917
    connect(sessionManager(), SIGNAL(sessionLoaded()),
918
       manager, SLOT(sessionLoaded()));
919
    connect(sessionManager(), SIGNAL(aboutToSaveSession()),
920
       manager, SLOT(aboutToSaveSession()));
921
    connect(sessionManager(), SIGNAL(aboutToUnloadSession()),