debuggerplugin.cpp 56 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>
46 47
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
hjk's avatar
hjk committed
48
#include <coreplugin/basemode.h>
con's avatar
con committed
49
#include <coreplugin/coreconstants.h>
50
#include <coreplugin/dialogs/ioptionspage.h>
con's avatar
con committed
51
#include <coreplugin/editormanager/editormanager.h>
hjk's avatar
hjk committed
52
#include <coreplugin/findplaceholder.h>
con's avatar
con committed
53
#include <coreplugin/icore.h>
54
#include <coreplugin/icorelistener.h>
55
#include <coreplugin/manhattanstyle.h>
con's avatar
con committed
56
#include <coreplugin/messagemanager.h>
hjk's avatar
hjk committed
57
#include <coreplugin/minisplitter.h>
con's avatar
con committed
58
#include <coreplugin/modemanager.h>
hjk's avatar
hjk committed
59 60 61
#include <coreplugin/navigationwidget.h>
#include <coreplugin/outputpane.h>
#include <coreplugin/rightpane.h>
con's avatar
con committed
62
#include <coreplugin/uniqueidmanager.h>
hjk's avatar
hjk committed
63

con's avatar
con committed
64
#include <cplusplus/ExpressionUnderCursor.h>
hjk's avatar
hjk committed
65

con's avatar
con committed
66
#include <cppeditor/cppeditorconstants.h>
hjk's avatar
hjk committed
67

68 69
#include <extensionsystem/pluginmanager.h>

70
#include <projectexplorer/project.h>
71
#include <projectexplorer/projectexplorer.h>
con's avatar
con committed
72 73
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/session.h>
74
#include <projectexplorer/toolchain.h>
hjk's avatar
hjk committed
75 76

#include <texteditor/basetexteditor.h>
con's avatar
con committed
77 78 79
#include <texteditor/basetextmark.h>
#include <texteditor/itexteditor.h>
#include <texteditor/texteditorconstants.h>
80
#include <texteditor/texteditorsettings.h>
hjk's avatar
hjk committed
81 82

#include <utils/qtcassert.h>
83
#include <utils/styledbar.h>
84
#include <utils/savedaction.h>
con's avatar
con committed
85 86 87 88 89

#include <QtCore/QDebug>
#include <QtCore/QObject>
#include <QtCore/QPoint>
#include <QtCore/QSettings>
90
#include <QtCore/QtPlugin>
91
#include <QtCore/QCoreApplication>
92
#include <QtCore/QTimer>
93
#include <QtCore/QVariant>
hjk's avatar
hjk committed
94

95
#include <QtGui/QLineEdit>
96
#include <QtGui/QDockWidget>
con's avatar
con committed
97 98 99
#include <QtGui/QPlainTextEdit>
#include <QtGui/QTextBlock>
#include <QtGui/QTextCursor>
100
#include <QtGui/QToolButton>
101
#include <QtGui/QMessageBox>
102 103
#include <QtGui/QAction>
#include <QtGui/QMenu>
con's avatar
con committed
104

105 106
#include <climits>

con's avatar
con committed
107
using namespace Core;
108
using namespace Debugger;
hjk's avatar
hjk committed
109 110
using namespace Debugger::Constants;
using namespace Debugger::Internal;
con's avatar
con committed
111
using namespace ProjectExplorer;
hjk's avatar
hjk committed
112
using namespace TextEditor;
con's avatar
con committed
113

hjk's avatar
hjk committed
114 115 116
namespace CC = Core::Constants;
namespace PE = ProjectExplorer::Constants;

con's avatar
con committed
117 118 119 120

namespace Debugger {
namespace Constants {

121 122
const char * const M_DEBUG_START_DEBUGGING = "QtCreator.Menu.Debug.StartDebugging";

con's avatar
con committed
123 124
const char * const STARTEXTERNAL        = "Debugger.StartExternal";
const char * const ATTACHEXTERNAL       = "Debugger.AttachExternal";
125
const char * const ATTACHCORE           = "Debugger.AttachCore";
hjk's avatar
hjk committed
126
const char * const ATTACHTCF            = "Debugger.AttachTcf";
127
const char * const ATTACHREMOTE         = "Debugger.AttachRemote";
128
const char * const DETACH               = "Debugger.Detach";
con's avatar
con committed
129

130 131
const char * const RUN_TO_LINE1         = "Debugger.RunToLine1";
const char * const RUN_TO_LINE2         = "Debugger.RunToLine2";
con's avatar
con committed
132
const char * const RUN_TO_FUNCTION      = "Debugger.RunToFunction";
133 134
const char * const JUMP_TO_LINE1        = "Debugger.JumpToLine1";
const char * const JUMP_TO_LINE2        = "Debugger.JumpToLine2";
135
const char * const RETURN_FROM_FUNCTION = "Debugger.ReturnFromFunction";
136
const char * const SNAPSHOT             = "Debugger.Snapshot";
con's avatar
con committed
137 138 139
const char * const TOGGLE_BREAK         = "Debugger.ToggleBreak";
const char * const BREAK_BY_FUNCTION    = "Debugger.BreakByFunction";
const char * const BREAK_AT_MAIN        = "Debugger.BreakAtMain";
140 141
const char * const ADD_TO_WATCH1        = "Debugger.AddToWatch1";
const char * const ADD_TO_WATCH2        = "Debugger.AddToWatch2";
142
const char * const OPERATE_BY_INSTRUCTION  = "Debugger.OperateByInstruction";
143 144
const char * const FRAME_UP             = "Debugger.FrameUp";
const char * const FRAME_DOWN           = "Debugger.FrameDown";
con's avatar
con committed
145

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
146
#ifdef Q_WS_MAC
con's avatar
con committed
147 148 149 150 151
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";
152
const char * const REVERSE_KEY              = "";
con's avatar
con committed
153 154 155 156 157 158 159
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";
160
const char * const SNAPSHOT_KEY             = "Alt+D,Alt+S";
con's avatar
con committed
161 162 163 164 165 166
#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";
167
const char * const REVERSE_KEY              = "F12";
con's avatar
con committed
168 169 170 171 172 173 174
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";
175
const char * const SNAPSHOT_KEY             = "Alt+D,Alt+S";
con's avatar
con committed
176 177 178 179 180 181
#endif

} // namespace Constants
} // namespace Debugger


182 183 184 185 186
static ProjectExplorer::SessionManager *sessionManager()
{
    return ProjectExplorer::ProjectExplorerPlugin::instance()->session();
}

187 188 189 190 191
static QSettings *settings()
{
    return ICore::instance()->settings();
}

192 193 194 195 196 197 198
static QToolButton *toolButton(QAction *action)
{
    QToolButton *button = new QToolButton;
    button->setDefaultAction(action);
    return button;
}

199 200 201 202 203 204
///////////////////////////////////////////////////////////////////////
//
// DebugMode
//
///////////////////////////////////////////////////////////////////////

hjk's avatar
hjk committed
205 206 207 208 209 210 211 212 213 214 215 216 217
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
218
  : BaseMode(parent)
hjk's avatar
hjk committed
219
{
220
    setDisplayName(tr("Debug"));
hjk's avatar
hjk committed
221
    setId(MODE_DEBUG);
hjk's avatar
hjk committed
222
    setIcon(QIcon(":/fancyactionbar/images/mode_Debug.png"));
hjk's avatar
hjk committed
223
    setPriority(P_MODE_DEBUG);
hjk's avatar
hjk committed
224 225 226 227 228 229 230 231
}

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

232 233 234 235 236 237
///////////////////////////////////////////////////////////////////////
//
// DebuggerListener: Close the debugging session if running.
//
///////////////////////////////////////////////////////////////////////

238 239
class DebuggerListener : public Core::ICoreListener
{
240 241
    Q_OBJECT
public:
hjk's avatar
hjk committed
242
    DebuggerListener() {}
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
    virtual bool coreAboutToClose();
};

bool DebuggerListener::coreAboutToClose()
{
    DebuggerManager *mgr = DebuggerManager::instance();
    if (!mgr)
        return true;
    // Ask to terminate the 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;
    }
hjk's avatar
hjk committed
267

268
    const QString question = cleanTermination ?
hjk's avatar
hjk committed
269 270 271 272
        tr("A debugging session is still in progress.\n"
           "Would you like to terminate it?") :
        tr("A debugging session is still in progress. "
           "Terminating the session in the current"
273
           " state (%1) can leave the target in an inconsistent state."
274
           " Would you still like to terminate it?")
hjk's avatar
hjk committed
275 276 277 278 279 280 281
        .arg(_(DebuggerManager::stateName(mgr->state())));

    QMessageBox::StandardButton answer =
        QMessageBox::question(DebuggerUISwitcher::instance()->mainWindow(),
            tr("Close Debugging Session"), question,
            QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes);

282
    if (answer != QMessageBox::Yes)
283
        return false;
hjk's avatar
hjk committed
284

285
    mgr->exitDebugger();
286
    QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
287 288 289
    return true;
}

290 291 292
} // namespace Internal
} // namespace Debugger

hjk's avatar
hjk committed
293

con's avatar
con committed
294 295 296 297 298 299
///////////////////////////////////////////////////////////////////////
//
// LocationMark
//
///////////////////////////////////////////////////////////////////////

300 301 302
namespace Debugger {
namespace Internal {

303
// Used in "real" editors
304
class LocationMark : public TextEditor::BaseTextMark
con's avatar
con committed
305 306 307 308 309 310
{
    Q_OBJECT

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

313
    QIcon icon() const { return DebuggerManager::instance()->locationMarkIcon(); }
con's avatar
con committed
314 315
    void updateLineNumber(int /*lineNumber*/) {}
    void updateBlock(const QTextBlock & /*block*/) {}
316
    void removedFromEditor() {}
con's avatar
con committed
317 318
};

319 320 321 322 323 324
} // namespace Internal
} // namespace Debugger


///////////////////////////////////////////////////////////////////////
//
325
// CommonOptionsPage
326 327 328 329 330 331
//
///////////////////////////////////////////////////////////////////////

namespace Debugger {
namespace Internal {

332
class CommonOptionsPage : public Core::IOptionsPage
333 334 335 336
{
    Q_OBJECT

public:
337
    CommonOptionsPage() {}
338 339

    // IOptionsPage
340
    QString id() const
hjk's avatar
hjk committed
341
        { return _(DEBUGGER_COMMON_SETTINGS_ID); }
342
    QString displayName() const
hjk's avatar
hjk committed
343
        { return QCoreApplication::translate("Debugger", DEBUGGER_COMMON_SETTINGS_NAME); }
344
    QString category() const
hjk's avatar
hjk committed
345
        { return _(DEBUGGER_SETTINGS_CATEGORY);  }
346
    QString displayCategory() const
hjk's avatar
hjk committed
347
        { return QCoreApplication::translate("Debugger", DEBUGGER_SETTINGS_TR_CATEGORY); }
348 349
    QIcon categoryIcon() const
        { return QIcon(QLatin1String(DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON)); }
350 351

    QWidget *createPage(QWidget *parent);
352
    void apply() { m_group.apply(settings()); }
353
    void finish() { m_group.finish(); }
354
    virtual bool matches(const QString &s) const;
355 356

private:
357
    Ui::CommonOptionsPage m_ui;
358
    Utils::SavedActionSet m_group;
359
    QString m_searchKeywords;
360 361
};

362
QWidget *CommonOptionsPage::createPage(QWidget *parent)
363 364 365
{
    QWidget *w = new QWidget(parent);
    m_ui.setupUi(w);
366
    m_group.clear();
367

368 369 370
    m_group.insert(theDebuggerAction(SwitchLanguageAutomatically),
        m_ui.checkBoxChangeLanguageAutomatically);

371
    m_group.insert(theDebuggerAction(ListSourceFiles),
372
        m_ui.checkBoxListSourceFiles);
373
    m_group.insert(theDebuggerAction(UseAlternatingRowColors),
374
        m_ui.checkBoxUseAlternatingRowColors);
375
    m_group.insert(theDebuggerAction(UseToolTipsInMainEditor),
376
        m_ui.checkBoxUseToolTipsInMainEditor);
377
    m_group.insert(theDebuggerAction(AutoDerefPointers), 0);
378 379 380 381
    m_group.insert(theDebuggerAction(UseToolTipsInLocalsView), 0);
    m_group.insert(theDebuggerAction(UseToolTipsInBreakpointsView), 0);
    m_group.insert(theDebuggerAction(UseAddressInBreakpointsView), 0);
    m_group.insert(theDebuggerAction(UseAddressInStackView), 0);
382
    m_group.insert(theDebuggerAction(MaximalStackDepth),
383
        m_ui.spinBoxMaximalStackDepth);
384 385
    m_group.insert(theDebuggerAction(ShowStdNamespace), 0);
    m_group.insert(theDebuggerAction(ShowQtNamespace), 0);
386
    m_group.insert(theDebuggerAction(LogTimeStamps), 0);
387
    m_group.insert(theDebuggerAction(VerboseLog), 0);
388
    m_group.insert(theDebuggerAction(UsePreciseBreakpoints), 0);
389 390
    m_group.insert(theDebuggerAction(BreakOnThrow), 0);
    m_group.insert(theDebuggerAction(BreakOnCatch), 0);
391 392 393 394 395 396 397
#ifdef Q_OS_WIN
    Utils::SavedAction *registerAction = theDebuggerAction(RegisterForPostMortem);
    m_group.insert(registerAction,
        m_ui.checkBoxRegisterForPostMortem);
    connect(registerAction, SIGNAL(toggled(bool)),
            m_ui.checkBoxRegisterForPostMortem, SLOT(setChecked(bool)));
#endif
398

399
    if (m_searchKeywords.isEmpty()) {
400 401 402
        QTextStream(&m_searchKeywords) << ' '
                << m_ui.checkBoxChangeLanguageAutomatically->text()
                << m_ui.checkBoxListSourceFiles->text()
403 404
                << ' ' << m_ui.checkBoxUseAlternatingRowColors->text()
                << ' ' << m_ui.checkBoxUseToolTipsInMainEditor->text()
405 406 407
#ifdef Q_OS_WIN
                << ' ' << m_ui.checkBoxRegisterForPostMortem->text()
#endif
408 409 410
                << ' ' << m_ui.labelMaximalStackDepth->text();
        m_searchKeywords.remove(QLatin1Char('&'));
    }
411 412 413
#ifndef Q_OS_WIN
    m_ui.checkBoxRegisterForPostMortem->setVisible(false);
#endif
414 415 416
    return w;
}

417 418 419 420 421
bool CommonOptionsPage::matches(const QString &s) const
{
    return m_searchKeywords.contains(s, Qt::CaseInsensitive);
}

422 423 424
} // namespace Internal
} // namespace Debugger

hjk's avatar
hjk committed
425

hjk's avatar
hjk committed
426 427
///////////////////////////////////////////////////////////////////////
//
428
// DebuggingHelperOptionPage
hjk's avatar
hjk committed
429 430 431
//
///////////////////////////////////////////////////////////////////////

432 433 434
static inline bool oxygenStyle()
{
    if (const ManhattanStyle *ms = qobject_cast<const ManhattanStyle *>(qApp->style()))
435
        return !qstrcmp("OxygenStyle", ms->baseStyle()->metaObject()->className());
436 437 438
    return false;
}

hjk's avatar
hjk committed
439 440 441
namespace Debugger {
namespace Internal {

442
class DebuggingHelperOptionPage : public Core::IOptionsPage
hjk's avatar
hjk committed
443 444 445 446
{
    Q_OBJECT

public:
447
    DebuggingHelperOptionPage() {}
hjk's avatar
hjk committed
448 449

    // IOptionsPage
hjk's avatar
hjk committed
450
    QString id() const { return _("Z.DebuggingHelper"); }
451
    QString displayName() const { return tr("Debugging Helper"); }
hjk's avatar
hjk committed
452 453
    QString category() const { return _(DEBUGGER_SETTINGS_CATEGORY); }
    QString displayCategory() const { return QCoreApplication::translate("Debugger", DEBUGGER_SETTINGS_TR_CATEGORY); }
454
    QIcon categoryIcon() const { return QIcon(QLatin1String(DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON)); }
hjk's avatar
hjk committed
455 456

    QWidget *createPage(QWidget *parent);
457
    void apply() { m_group.apply(settings()); }
458
    void finish() { m_group.finish(); }
459
    virtual bool matches(const QString &s) const;
hjk's avatar
hjk committed
460 461

private:
462
    Ui::DebuggingHelperOptionPage m_ui;
463
    Utils::SavedActionSet m_group;
464
    QString m_searchKeywords;
hjk's avatar
hjk committed
465 466
};

467
QWidget *DebuggingHelperOptionPage::createPage(QWidget *parent)
hjk's avatar
hjk committed
468 469 470 471
{
    QWidget *w = new QWidget(parent);
    m_ui.setupUi(w);

472
    m_ui.dumperLocationChooser->setExpectedKind(Utils::PathChooser::Command);
473
    m_ui.dumperLocationChooser->setPromptDialogTitle(tr("Choose DebuggingHelper Location"));
hjk's avatar
hjk committed
474 475
    m_ui.dumperLocationChooser->setInitialBrowsePathBackup(
        Core::ICore::instance()->resourcePath() + "../../lib");
hjk's avatar
hjk committed
476

477
    m_group.clear();
478
    m_group.insert(theDebuggerAction(UseDebuggingHelpers),
479
        m_ui.debuggingHelperGroupBox);
480
    m_group.insert(theDebuggerAction(UseCustomDebuggingHelperLocation),
481
        m_ui.customLocationGroupBox);
hjk's avatar
hjk committed
482
    // Suppress Oxygen style's giving flat group boxes bold titles.
483
    if (oxygenStyle())
hjk's avatar
hjk committed
484
        m_ui.customLocationGroupBox->setStyleSheet(_("QGroupBox::title { font: ; }"));
485

486
    m_group.insert(theDebuggerAction(CustomDebuggingHelperLocation),
487
        m_ui.dumperLocationChooser);
hjk's avatar
hjk committed
488

489 490 491
    m_group.insert(theDebuggerAction(UseCodeModel),
        m_ui.checkBoxUseCodeModel);

492
#ifdef QT_DEBUG
493 494
    m_group.insert(theDebuggerAction(DebugDebuggingHelpers),
        m_ui.checkBoxDebugDebuggingHelpers);
495 496 497
#else
    m_ui.checkBoxDebugDebuggingHelpers->hide();
#endif
hjk's avatar
hjk committed
498 499 500 501

#ifndef QT_DEBUG
#if 0
    cmd = am->registerAction(m_manager->m_dumpLogAction,
hjk's avatar
hjk committed
502
        DUMP_LOG, globalcontext);
hjk's avatar
hjk committed
503 504 505 506 507 508
    //cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+D,Ctrl+L")));
    cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+F11")));
    mdebug->addAction(cmd);
#endif
#endif

509 510 511 512 513 514 515 516 517
    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
518 519 520
    return w;
}

521
bool DebuggingHelperOptionPage::matches(const QString &s) const
hjk's avatar
hjk committed
522
{
523
    return m_searchKeywords.contains(s, Qt::CaseInsensitive);
hjk's avatar
hjk committed
524 525
}

hjk's avatar
hjk committed
526 527 528
} // namespace Internal
} // namespace Debugger

529

con's avatar
con committed
530 531 532 533 534 535
///////////////////////////////////////////////////////////////////////
//
// DebuggerPlugin
//
///////////////////////////////////////////////////////////////////////

536 537 538 539 540 541 542

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

543 544
DebuggerPlugin::DebuggerPlugin()
  : m_manager(0),
545 546 547
    m_debugMode(0),
    m_locationMark(0),
    m_gdbRunningContext(0),
548
    m_cmdLineEnabledEngines(AllEngineTypes)
549
{}
con's avatar
con committed
550 551 552

DebuggerPlugin::~DebuggerPlugin()
{
dt's avatar
dt committed
553
    delete DebuggerSettings::instance();
hjk's avatar
hjk committed
554

con's avatar
con committed
555 556 557 558 559 560 561 562
    removeObject(m_debugMode);

    delete m_debugMode;
    m_debugMode = 0;

    delete m_locationMark;
    m_locationMark = 0;

ck's avatar
ck committed
563
    removeObject(m_manager);
con's avatar
con committed
564 565
    delete m_manager;
    m_manager = 0;
566 567 568 569

    removeObject(m_uiSwitcher);
    delete m_uiSwitcher;
    m_uiSwitcher = 0;
con's avatar
con committed
570 571
}

572
void DebuggerPlugin::aboutToShutdown()
573 574 575
{
    QTC_ASSERT(m_manager, /**/);
    if (m_manager)
576
        m_manager->aboutToShutdown();
577 578 579 580

    writeSettings();

    if (m_uiSwitcher)
581
        m_uiSwitcher->aboutToShutdown();
582 583
}

584
static QString msgParameterMissing(const QString &a)
585 586 587 588
{
    return DebuggerPlugin::tr("Option '%1' is missing the parameter.").arg(a);
}

589
static QString msgInvalidNumericParameter(const QString &a, const QString &number)
590 591 592 593 594
{
    return DebuggerPlugin::tr("The parameter '%1' of option '%2' is not a number.").arg(number, a);
}

// Parse arguments
595 596 597 598
static bool parseArgument(QStringList::const_iterator &it,
                          const QStringList::const_iterator &cend,
                          DebuggerPlugin::AttachRemoteParameters *attachRemoteParameters,
                          unsigned *enabledEngines, QString *errorMessage)
599 600 601
{
    const QString &option = *it;
    // '-debug <pid>'
hjk's avatar
hjk committed
602
    if (*it == _("-debug")) {
603 604 605 606 607 608
        ++it;
        if (it == cend) {
            *errorMessage = msgParameterMissing(*it);
            return false;
        }
        bool ok;
609
        attachRemoteParameters->attachPid = it->toULongLong(&ok);
610
        if (!ok) {
611 612
            attachRemoteParameters->attachPid = 0;
            attachRemoteParameters->attachCore = *it;
613 614 615
        }
        return true;
    }
616 617
    // -wincrashevent <event-handle>. A handle used for
    // a handshake when attaching to a crashed Windows process.
hjk's avatar
hjk committed
618
    if (*it == _("-wincrashevent")) {
619 620 621 622 623 624
        ++it;
        if (it == cend) {
            *errorMessage = msgParameterMissing(*it);
            return false;
        }
        bool ok;
625
        attachRemoteParameters->winCrashEvent = it->toULongLong(&ok);
626 627 628 629 630 631
        if (!ok) {
            *errorMessage = msgInvalidNumericParameter(option, *it);
            return false;
        }
        return true;
    }
hjk's avatar
hjk committed
632
    // Engine disabling.
hjk's avatar
hjk committed
633
    if (option == _("-disable-cdb")) {
634
        *enabledEngines &= ~Debugger::CdbEngineType;
635 636
        return true;
    }
hjk's avatar
hjk committed
637
    if (option == _("-disable-gdb")) {
638
        *enabledEngines &= ~Debugger::GdbEngineType;
639 640
        return true;
    }
641 642 643 644
    if (option == _("-disable-qmldb")) {
        *enabledEngines &= ~Debugger::QmlEngineType;
        return true;
    }
hjk's avatar
hjk committed
645
    if (option == _("-disable-sdb")) {
646
        *enabledEngines &= ~Debugger::ScriptEngineType;
647 648
        return true;
    }
649
    if (option == _("-disable-tcf")) {
hjk's avatar
hjk committed
650 651 652
        *enabledEngines &= ~TcfEngineType;
        return true;
    }
653

654
    *errorMessage = DebuggerPlugin::tr("Invalid debugger option: %1").arg(option);
655 656 657
    return false;
}

658
static bool parseArguments(const QStringList &args,
hjk's avatar
hjk committed
659 660
   DebuggerPlugin::AttachRemoteParameters *attachRemoteParameters,
   unsigned *enabledEngines, QString *errorMessage)
661 662 663
{
    const QStringList::const_iterator cend = args.constEnd();
    for (QStringList::const_iterator it = args.constBegin(); it != cend; ++it)
664
        if (!parseArgument(it, cend, attachRemoteParameters, enabledEngines, errorMessage))
665 666
            return false;
    if (Debugger::Constants::Internal::debug)
667
        qDebug().nospace() << args << "engines=0x"
668 669 670
            << QString::number(*enabledEngines, 16)
            << " pid" << attachRemoteParameters->attachPid
            << " core" << attachRemoteParameters->attachCore << '\n';
671 672 673
    return true;
}

674 675 676 677 678 679 680 681 682 683 684 685 686
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
687
bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMessage)
con's avatar
con committed
688
{
hjk's avatar
hjk committed
689
    // Do not fail the whole plugin if something goes wrong here.
690
    if (!parseArguments(arguments, &m_attachRemoteParameters, &m_cmdLineEnabledEngines, errorMessage)) {
691 692
        *errorMessage = tr("Error evaluating command line arguments: %1")
            .arg(*errorMessage);
693 694 695
        qWarning("%s\n", qPrintable(*errorMessage));
        errorMessage->clear();
    }
con's avatar
con committed
696

hjk's avatar
hjk committed
697
    // Debug mode setup.
698 699 700 701
    m_debugMode = new DebugMode(this);
    m_uiSwitcher = new DebuggerUISwitcher(m_debugMode, this);
    ExtensionSystem::PluginManager::instance()->addObject(m_uiSwitcher);

702
    ICore *core = ICore::instance();
hjk's avatar
hjk committed
703
    QTC_ASSERT(core, return false);
con's avatar
con committed
704

705 706
    Core::ActionManager *am = core->actionManager();
    QTC_ASSERT(am, return false);
con's avatar
con committed
707 708

    Core::UniqueIDManager *uidm = core->uniqueIDManager();
hjk's avatar
hjk committed
709
    QTC_ASSERT(uidm, return false);
con's avatar
con committed
710 711

    QList<int> globalcontext;
hjk's avatar
hjk committed
712
    globalcontext << CC::C_GLOBAL_ID;
con's avatar
con committed
713 714

    QList<int> cppcontext;
hjk's avatar
hjk committed
715
    cppcontext << uidm->uniqueIdentifier(PE::LANG_CXX);
con's avatar
con committed
716

717 718
    QList<int> cppDebuggercontext;
    cppDebuggercontext << uidm->uniqueIdentifier(C_CPPDEBUGGER);
con's avatar
con committed
719 720

    QList<int> cppeditorcontext;
721
    cppeditorcontext << uidm->uniqueIdentifier(CppEditor::Constants::C_CPPEDITOR);
con's avatar
con committed
722 723 724 725 726 727

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

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

728
    m_uiSwitcher->addLanguage(LANG_CPP, cppDebuggercontext);
729

730 731 732 733 734
    DebuggerManager *manager = new DebuggerManager(this);
    ExtensionSystem::PluginManager::instance()->addObject(manager);
    const QList<Core::IOptionsPage *> engineOptionPages =
        manager->initializeEngines(m_cmdLineEnabledEngines);

735
    // Register factory of DebuggerRunControl.
736
    m_debuggerRunControlFactory = new DebuggerRunControlFactory(manager);
737 738 739
    addAutoReleasedObject(m_debuggerRunControlFactory);

    QList<int> context;
hjk's avatar
hjk committed
740
    context.append(uidm->uniqueIdentifier(CC::C_EDITORMANAGER));
741
    context.append(uidm->uniqueIdentifier(C_DEBUGMODE));
hjk's avatar
hjk committed
742
    context.append(uidm->uniqueIdentifier(CC::C_NAVIGATION_PANE));
743 744
    m_debugMode->setContext(context);

745
    m_reverseToolButton = 0;
con's avatar
con committed
746

747
    // Handling of external applications.
748 749 750 751 752 753 754 755 756 757 758 759 760 761
    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()));

hjk's avatar
hjk committed
762 763 764 765 766 767 768
    m_attachTcfAction = new QAction(this);
    m_attachTcfAction->setText(tr("Attach to Running Tcf Agent..."));
    m_attachTcfAction->setToolTip(tr("This attaches to a running "
        "'Target Communication Framework' agent."));
    connect(m_attachTcfAction, SIGNAL(triggered()),
        this, SLOT(attachRemoteTcf()));

769 770 771 772
    m_startRemoteAction = new QAction(this);
    m_startRemoteAction->setText(tr("Start and Attach to Remote Application..."));
    connect(m_startRemoteAction, SIGNAL(triggered()),
        this, SLOT(startRemoteApplication()));
773

774
    m_detachAction = new QAction(this);
775
    m_detachAction->setText(tr("Detach Debugger"));
776
    connect(m_detachAction, SIGNAL(triggered()),
777
        manager, SLOT(detachDebugger()));
778

779
    Core::Command *cmd = 0;
780
    const DebuggerManagerActions actions = manager->debuggerManagerActions();
781

782
    Core::ActionContainer *mstart =
hjk's avatar
hjk committed
783
        am->actionContainer(PE::M_DEBUG_STARTDEBUGGING);
784

785
    cmd = am->registerAction(actions.continueAction,
hjk's avatar
hjk committed
786 787
        PE::DEBUG, QList<int>() << m_gdbRunningContext);
    mstart->addAction(cmd, CC::G_DEFAULT_ONE);
788

789
    cmd = am->registerAction(m_startExternalAction,
con's avatar
con committed
790
        Constants::STARTEXTERNAL, globalcontext);
791
    cmd->setAttribute(Command::CA_Hide);
hjk's avatar
hjk committed
792
    mstart->addAction(cmd, CC::G_DEFAULT_ONE);
con's avatar
con committed
793

794
    cmd = am->registerAction(m_attachExternalAction,
con's avatar
con committed
795
        Constants::ATTACHEXTERNAL, globalcontext);
796
    cmd->setAttribute(Command::CA_Hide);
hjk's avatar
hjk committed
797
    mstart->addAction(cmd, CC::G_DEFAULT_ONE);
798

799 800
    cmd = am->registerAction(m_attachCoreAction,
        Constants::ATTACHCORE, globalcontext);
hjk's avatar
hjk committed
801

802
    cmd->setAttribute(Command::CA_Hide);
hjk's avatar
hjk committed
803
    mstart->addAction(cmd, CC::G_DEFAULT_ONE);
804

hjk's avatar
hjk committed
805 806 807 808
    cmd = am->registerAction(m_attachTcfAction,
        Constants::ATTACHTCF, globalcontext);
    mstart->addAction(cmd, Core::Constants::G_DEFAULT_ONE);

809
    cmd = am->registerAction(m_startRemoteAction,
810
        Constants::ATTACHREMOTE, globalcontext);
811
    cmd->setAttribute(Command::CA_Hide);
hjk's avatar
hjk committed
812
    mstart->addAction(cmd, CC::G_DEFAULT_ONE);
813

814 815
    cmd = am->registerAction(m_detachAction,
        Constants::DETACH, globalcontext);
816
    cmd->setAttribute(Command::CA_Hide);
hjk's avatar
hjk committed
817
    m_uiSwitcher->addMenuAction(cmd, CC::G_DEFAULT_ONE);
con's avatar
con committed
818

819
    cmd = am->registerAction(actions.stopAction,
con's avatar
con committed
820
        Constants::INTERRUPT, globalcontext);
hjk's avatar
hjk committed
821 822
    cmd->setAttribute(Command::CA_UpdateText);
    cmd->setAttribute(Command::CA_UpdateIcon);
con's avatar
con committed
823 824
    cmd->setDefaultKeySequence(QKeySequence(Constants::INTERRUPT_KEY));
    cmd->setDefaultText(tr("Stop Debugger/Interrupt Debugger"));
hjk's avatar
hjk committed
825
    m_uiSwitcher->addMenuAction(cmd, CC::G_DEFAULT_ONE);
con's avatar
con committed
826

827
    cmd = am->registerAction(actions.resetAction,
con's avatar
con committed
828
        Constants::RESET, globalcontext);
con's avatar
con committed
829
    cmd->setAttribute(Core::Command::CA_UpdateText);
830
    //cmd->setDefaultKeySequence(QKeySequence(Constants::RESET_KEY));
con's avatar
con committed
831
    cmd->setDefaultText(tr("Reset Debugger"));
hjk's avatar
hjk committed
832
    m_uiSwitcher->addMenuAction(cmd, CC::G_DEFAULT_ONE);
con's avatar
con committed
833 834 835

    QAction *sep = new QAction(this);
    sep->setSeparator(true);
hjk's avatar
hjk committed
836
    cmd = am->registerAction(sep, _("Debugger.Sep.Step"), globalcontext);
837
    m_uiSwitcher->addMenuAction(cmd, Constants::LANG_CPP);
con's avatar
con committed
838

839
    cmd = am->registerAction(actions.nextAction,
840
        Constants::NEXT, cppDebuggercontext);
con's avatar
con committed
841
    cmd->setDefaultKeySequence(QKeySequence(Constants::NEXT_KEY));
842
    cmd->setAttribute(Command::CA_Hide);
843
    m_uiSwitcher->addMenuAction(cmd, Constants::LANG_CPP);
con's avatar
con committed
844

845
    cmd = am->registerAction(actions.stepAction,
846
        Constants::STEP, cppDebuggercontext);
con's avatar
con committed
847
    cmd->setDefaultKeySequence(QKeySequence(Constants::STEP_KEY));
848
    cmd->setAttribute(Command::CA_Hide);
849 850
    m_uiSwitcher->addMenuAction(cmd, Constants::LANG_CPP);

con's avatar
con committed
851

852
    cmd = am->registerAction(actions.stepOutAction,
853
        Constants::STEPOUT, cppDebuggercontext);
con's avatar
con committed
854
    cmd->setDefaultKeySequence(QKeySequence(Constants::STEPOUT_KEY));
855
    cmd->setAttribute(Command::CA_Hide);
856 857
    m_uiSwitcher->addMenuAction(cmd, Constants::LANG_CPP);

con's avatar
con committed
858

859
    cmd = am->registerAction(actions.runToLineAction1,
860
        Constants::RUN_TO_LINE1, cppDebuggercontext);
con's avatar
con committed
861
    cmd->setDefaultKeySequence(QKeySequence(Constants::RUN_TO_LINE_KEY));
862
    cmd->setAttribute(Command::CA_Hide);
863 864
    m_uiSwitcher->addMenuAction(cmd, Constants::LANG_CPP);

con's avatar
con committed
865