1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
10 ** GNU Lesser General Public License Usage
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at info@qt.nokia.com.
31 **************************************************************************/
33 #include "debuggerplugin.h"
35 #include "debuggerstartparameters.h"
36 #include "debuggeractions.h"
37 #include "debuggerconstants.h"
38 #include "debuggerinternalconstants.h"
39 #include "debuggercore.h"
40 #include "debuggerdialogs.h"
41 #include "debuggerengine.h"
42 #include "debuggermainwindow.h"
43 #include "debuggerrunner.h"
44 #include "debuggerruncontrolfactory.h"
45 #include "debuggerstringutils.h"
46 #include "memoryagent.h"
47 #include "breakpoint.h"
48 #include "breakhandler.h"
49 #include "breakwindow.h"
50 #include "consolewindow.h"
51 #include "disassemblerlines.h"
52 #include "logwindow.h"
53 #include "moduleswindow.h"
54 #include "moduleshandler.h"
55 #include "registerwindow.h"
56 #include "snapshotwindow.h"
57 #include "stackhandler.h"
58 #include "stackwindow.h"
59 #include "sourcefileswindow.h"
60 #include "threadswindow.h"
61 #include "watchhandler.h"
62 #include "watchwindow.h"
63 #include "watchutils.h"
64 #include "debuggertooltipmanager.h"
65 #include "qml/qmlengine.h"
66 #include "qml/qmlcppengine.h"
68 #include "snapshothandler.h"
69 #include "threadshandler.h"
70 #include "commonoptionspage.h"
72 #include <coreplugin/actionmanager/actionmanager.h>
73 #include <coreplugin/actionmanager/actioncontainer.h>
74 #include <coreplugin/actionmanager/command.h>
75 #include <coreplugin/id.h>
76 #include <coreplugin/imode.h>
77 #include <coreplugin/coreconstants.h>
78 #include <coreplugin/dialogs/ioptionspage.h>
79 #include <coreplugin/editormanager/editormanager.h>
80 #include <coreplugin/findplaceholder.h>
81 #include <coreplugin/icontext.h>
82 #include <coreplugin/icore.h>
83 #include <coreplugin/imode.h>
84 #include <coreplugin/icorelistener.h>
85 #include <coreplugin/minisplitter.h>
86 #include <coreplugin/modemanager.h>
88 #include <cppeditor/cppeditorconstants.h>
89 #include <cplusplus/ModelManagerInterface.h>
91 #include <extensionsystem/pluginmanager.h>
93 #include <projectexplorer/project.h>
94 #include <projectexplorer/projectexplorer.h>
95 #include <projectexplorer/projectexplorerconstants.h>
96 #include <projectexplorer/toolchainmanager.h>
97 #include <projectexplorer/toolchain.h>
98 #include <projectexplorer/session.h>
99 #include <projectexplorer/target.h>
100 #include <projectexplorer/abi.h>
102 #include <qtsupport/qtsupportconstants.h>
104 #include <texteditor/basetexteditor.h>
105 #include <texteditor/fontsettings.h>
106 #include <texteditor/texteditorsettings.h>
108 #include <utils/qtcassert.h>
109 #include <utils/savedaction.h>
110 #include <utils/styledbar.h>
111 #include <utils/proxyaction.h>
112 #include <utils/statuslabel.h>
113 #include <utils/fileutils.h>
115 #include <qml/scriptconsole.h>
117 #include <QtCore/QTimer>
118 #include <QtCore/QtPlugin>
119 #include <QtGui/QComboBox>
120 #include <QtGui/QDockWidget>
121 #include <QtGui/QFileDialog>
122 #include <QtGui/QMenu>
123 #include <QtGui/QMessageBox>
124 #include <QtGui/QPushButton>
125 #include <QtGui/QTextBlock>
126 #include <QtGui/QTextCursor>
127 #include <QtGui/QToolButton>
128 #include <QtGui/QTreeWidget>
129 #include <QtGui/QInputDialog>
133 #define DEBUG_STATE 1
135 //# define STATE_DEBUG(s)
136 // do { QString msg; QTextStream ts(&msg); ts << s;
137 // showMessage(msg, LogDebug); } while (0)
138 # define STATE_DEBUG(s) do { qDebug() << s; } while(0)
140 # define STATE_DEBUG(s)
145 Debugger plugin namespace
149 \namespace Debugger::Internal
150 Internal namespace of the Debugger plugin
155 \class Debugger::DebuggerEngine
157 \brief Base class of a debugger engine.
159 Note: the Debugger process itself and any helper processes like
160 gdbserver, the CODA client etc are referred to as 'Engine',
161 whereas the debugged process is referred to as 'Inferior'.
163 Transitions marked by '---' are done in the individual engines.
164 Transitions marked by '+-+' are done in the base DebuggerEngine.
165 Transitions marked by '*' are done asynchronously.
167 The GdbEngine->setupEngine() function is described in more detail below.
169 The engines are responsible for local roll-back to the last
170 acknowledged state before calling notify*Failed. I.e. before calling
171 notifyEngineSetupFailed() any process started during setupEngine()
172 so far must be terminated.
176 progressmanager/progressmanager.cpp +
179 (calls *Engine->setupEngine())
184 SetupOk} SetupFailed}
186 + `+-+-+> EngineSetupFailed
188 + [calls RunControl->startFailed]
194 [calls RunControl->StartSuccessful]
196 InferiorSetupRequested
198 (calls *Engine->setupInferior())
203 SetupOk} SetupFailed}
205 + ` +-+-> InferiorSetupFailed +-+-+-+-+-+->.
211 (calls *Engine->runEngine()) +
214 | (core) | (attach) | | +
216 {notify- {notifyER&- {notifyER&- {notify- +
217 Inferior- Inferior- Inferior- EngineRun- +
218 Unrunnable} StopOk} RunOk} Failed} +
220 InferiorUnrunnable + InferiorRunOk + +
222 InferiorStopOk EngineRunFailed +
224 `-+-+-+-+-+-+-+-+-+-+-+>-+
227 #Interrupt@InferiorRunOk# +
229 InferiorStopRequested +
231 @InferiorRunOk# (calls *Engine-> +
232 + interruptInferior()) +
234 Spontaneous- {notify- {notify- +
235 Inferior- Inferior- Inferior- +
236 StopOk} StopOk} StopFailed} +
243 #Stop@InferiorUnrunnable# + +
244 #Creator Close Event# + +
246 InferiorShutdownRequested +
248 (calls *Engine->shutdownInferior()) +
251 Inferior- Inferior- +
252 ShutdownOk} ShutdownFailed} +
255 #Inferior exited# + + +
257 {notifyInferior- + + +
262 InferiorShutdownOk InferiorShutdownFailed +
264 EngineShutdownRequested +
266 (calls *Engine->shutdownEngine()) <+-+-+-+-+-+-+-+-+-+-+-+-+-+'
271 ShutdownOk} ShutdownFailed}
273 EngineShutdownOk EngineShutdownFailed
279 /* Here is a matching graph as a GraphViz graph. View it using
281 grep "^sg1:" debuggerplugin.cpp | cut -c5- | dot -osg1.ps -Tps && gv sg1.ps
283 sg1: digraph DebuggerStates {
284 sg1: DebuggerNotReady -> EngineSetupRequested
285 sg1: EngineSetupRequested -> EngineSetupOk [ label="notifyEngineSetupOk", style="dashed" ];
286 sg1: EngineSetupRequested -> EngineSetupFailed [ label= "notifyEngineSetupFailed", style="dashed"];
287 sg1: EngineSetupFailed -> DebuggerFinished [ label= "RunControl::StartFailed" ];
288 sg1: EngineSetupOk -> InferiorSetupRequested [ label= "RunControl::StartSuccessful" ];
289 sg1: InferiorSetupRequested -> InferiorSetupOk [ label="notifyInferiorSetupOk", style="dashed" ];
290 sg1: InferiorSetupRequested -> InferiorSetupFailed [ label="notifyInferiorFailed", style="dashed" ];
291 sg1: InferiorSetupOk -> EngineRunRequested
292 sg1: InferiorSetupFailed -> EngineShutdownRequested
293 sg1: EngineRunRequested -> InferiorUnrunnable [ label="notifyInferiorUnrunnable", style="dashed" ];
294 sg1: EngineRunRequested -> InferiorStopOk [ label="notifyEngineRunAndInferiorStopOk", style="dashed" ];
295 sg1: EngineRunRequested -> InferiorRunOk [ label="notifyEngineRunAndInferiorRunOk", style="dashed" ];
296 sg1: EngineRunRequested -> EngineRunFailed [ label="notifyEngineRunFailed", style="dashed" ];
297 sg1: EngineRunFailed -> EngineShutdownRequested
298 sg1: InferiorRunOk -> InferiorStopOk [ label="SpontaneousStop\nnotifyInferiorSpontaneousStop", style="dashed" ];
299 sg1: InferiorRunOk -> InferiorStopRequested [ label="User stop\nEngine::interruptInferior", style="dashed"];
300 sg1: InferiorStopRequested -> InferiorStopOk [ label="notifyInferiorStopOk", style="dashed" ];
301 sg1: InferiorStopRequested -> InferiorShutdownRequested [ label="notifyInferiorStopFailed", style="dashed" ];
302 sg1: InferiorStopOk -> InferiorRunRequested [ label="User\nEngine::continueInferior" ];
303 sg1: InferiorRunRequested -> InferiorRunOk [ label="notifyInferiorRunOk", style="dashed"];
304 sg1: InferiorRunRequested -> InferiorRunFailed [ label="notifyInferiorRunFailed", style="dashed"];
305 sg1: InferiorRunFailed -> InferiorStopOk
306 sg1: InferiorStopOk -> InferiorShutdownRequested [ label="Close event" ];
307 sg1: InferiorUnrunnable -> InferiorShutdownRequested [ label="Close event" ];
308 sg1: InferiorShutdownRequested -> InferiorShutdownOk [ label= "Engine::shutdownInferior\nnotifyInferiorShutdownOk", style="dashed" ];
309 sg1: InferiorShutdownRequested -> InferiorShutdownFailed [ label="Engine::shutdownInferior\nnotifyInferiorShutdownFailed", style="dashed" ];
310 sg1: InferiorExited -> InferiorExitOk [ label="notifyInferiorExited", style="dashed"];
311 sg1: InferiorExitOk -> InferiorShutdownOk
312 sg1: InferiorShutdownOk -> EngineShutdownRequested
313 sg1: InferiorShutdownFailed -> EngineShutdownRequested
314 sg1: EngineShutdownRequested -> EngineShutdownOk [ label="Engine::shutdownEngine\nnotifyEngineShutdownOk", style="dashed" ];
315 sg1: EngineShutdownRequested -> EngineShutdownFailed [ label="Engine::shutdownEngine\nnotifyEngineShutdownFailed", style="dashed" ];
316 sg1: EngineShutdownOk -> DebuggerFinished [ style = "dotted" ];
317 sg1: EngineShutdownFailed -> DebuggerFinished [ style = "dotted" ];
320 // Additional signalling: {notifyInferiorIll} {notifyEngineIll}
324 \class Debugger::Internal::GdbEngine
325 \brief Implementation of Debugger::Engine driving a gdb executable.
327 GdbEngine specific startup. All happens in EngineSetupRequested state:
329 Transitions marked by '---' are done in the individual adapters.
331 Transitions marked by '+-+' are done in the GdbEngine.
334 GdbEngine::setupEngine()
336 (calls *Adapter->startAdapter())
338 | `---> handleAdapterStartFailed()
340 | {notifyEngineSetupFailed}
342 handleAdapterStarted()
344 {notifyEngineSetupOk}
348 GdbEngine::setupInferior()
350 (calls *Adapter->prepareInferior())
352 | `---> handlePrepareInferiorFailed()
354 | {notifyInferiorSetupFailed}
356 handleInferiorPrepared()
358 {notifyInferiorSetupOk}
362 using namespace Core;
363 using namespace Debugger::Constants;
364 using namespace ProjectExplorer;
365 using namespace TextEditor;
367 namespace CC = Core::Constants;
368 namespace PE = ProjectExplorer::Constants;
372 namespace Constants {
375 const char STOP_KEY[] = "Shift+Ctrl+Y";
376 const char RESET_KEY[] = "Ctrl+Shift+F5";
377 const char STEP_KEY[] = "Ctrl+Shift+I";
378 const char STEPOUT_KEY[] = "Ctrl+Shift+T";
379 const char NEXT_KEY[] = "Ctrl+Shift+O";
380 const char REVERSE_KEY[] = "";
381 const char RUN_TO_LINE_KEY[] = "Shift+F8";
382 const char RUN_TO_SELECTED_FUNCTION_KEY[] = "Ctrl+F6";
383 const char JUMP_TO_LINE_KEY[] = "Ctrl+D,Ctrl+L";
384 const char TOGGLE_BREAK_KEY[] = "F8";
385 const char BREAK_BY_FUNCTION_KEY[] = "Ctrl+D,Ctrl+F";
386 const char BREAK_AT_MAIN_KEY[] = "Ctrl+D,Ctrl+M";
387 const char ADD_TO_WATCH_KEY[] = "Ctrl+D,Ctrl+W";
388 const char SNAPSHOT_KEY[] = "Ctrl+D,Ctrl+S";
390 const char STOP_KEY[] = "Shift+F5";
391 const char RESET_KEY[] = "Ctrl+Shift+F5";
392 const char STEP_KEY[] = "F11";
393 const char STEPOUT_KEY[] = "Shift+F11";
394 const char NEXT_KEY[] = "F10";
395 const char REVERSE_KEY[] = "F12";
396 const char RUN_TO_LINE_KEY[] = "";
397 const char RUN_TO_SELECTED_FUNCTION_KEY[] = "Ctrl+F6";
398 const char JUMP_TO_LINE_KEY[] = "";
399 const char TOGGLE_BREAK_KEY[] = "F9";
400 const char BREAK_BY_FUNCTION_KEY[] = "";
401 const char BREAK_AT_MAIN_KEY[] = "";
402 const char ADD_TO_WATCH_KEY[] = "Ctrl+Alt+Q";
403 const char SNAPSHOT_KEY[] = "Ctrl+D,Ctrl+S";
406 } // namespace Constants
411 // To be passed through margin menu action's data
412 struct BreakpointMenuContextData : public ContextData
420 BreakpointMenuContextData() : mode(Breakpoint) {}
424 } // namespace Internal
425 } // namespace Debugger
427 Q_DECLARE_METATYPE(Debugger::Internal::BreakpointMenuContextData)
433 // The createCdbEngine function takes a list of options pages it can add to.
434 // This allows for having a "enabled" toggle on the page independently
435 // of the engine. That's good for not enabling the related ActiveX control
438 void addCdbOptionPages(QList<IOptionsPage*> *opts);
439 void addGdbOptionPages(QList<IOptionsPage*> *opts);
440 void addScriptOptionPages(QList<IOptionsPage*> *opts);
441 void addTcfOptionPages(QList<IOptionsPage*> *opts);
444 void addLldbOptionPages(QList<IOptionsPage*> *opts);
447 static SessionManager *sessionManager()
449 return ProjectExplorerPlugin::instance()->session();
452 static QToolButton *toolButton(QAction *action)
454 QToolButton *button = new QToolButton;
455 button->setDefaultAction(action);
459 static Abi anyAbiOfBinary(const QString &fileName)
461 QList<Abi> abis = Abi::abisOfBinary(fileName);
467 ///////////////////////////////////////////////////////////////////////
471 ///////////////////////////////////////////////////////////////////////
473 class DummyEngine : public DebuggerEngine
478 DummyEngine() : DebuggerEngine(DebuggerStartParameters(), AnyLanguage) {}
481 void setupEngine() {}
482 void setupInferior() {}
484 void shutdownEngine() {}
485 void shutdownInferior() {}
486 unsigned debuggerCapabilities() const { return AddWatcherCapability; }
487 bool acceptsBreakpoint(BreakpointModelId) const { return false; }
488 bool acceptsDebuggerCommands() const { return false; }
491 ///////////////////////////////////////////////////////////////////////
495 ///////////////////////////////////////////////////////////////////////
497 class DebugMode : public IMode
502 setObjectName(QLatin1String("DebugMode"));
503 setContext(Context(CC::C_EDITORMANAGER, C_DEBUGMODE, CC::C_NAVIGATION_PANE));
504 setDisplayName(DebuggerPlugin::tr("Debug"));
505 setIcon(QIcon(QLatin1String(":/fancyactionbar/images/mode_Debug.png")));
508 setType(CC::MODE_EDIT_TYPE);
513 // Make sure the editor manager does not get deleted.
514 //EditorManager::instance()->setParent(0);
520 ///////////////////////////////////////////////////////////////////////
524 ///////////////////////////////////////////////////////////////////////
526 static TextEditor::ITextEditor *currentTextEditor()
528 if (const Core::EditorManager *editorManager = Core::EditorManager::instance())
529 if (Core::IEditor *editor = editorManager->currentEditor())
530 return qobject_cast<TextEditor::ITextEditor*>(editor);
534 static bool currentTextEditorPosition(ContextData *data)
536 if (TextEditor::ITextEditor *textEditor = currentTextEditor()) {
537 if (const Core::IFile *file = textEditor->file()) {
538 data->fileName = file->fileName();
539 data->lineNumber = textEditor->currentLine();
546 ///////////////////////////////////////////////////////////////////////
548 // DebuggerPluginPrivate
550 ///////////////////////////////////////////////////////////////////////
552 static DebuggerPluginPrivate *theDebuggerCore = 0;
555 \class Debugger::Internal::DebuggerCore
557 This is the "internal" interface of the debugger plugin that's
558 used by debugger views and debugger engines. The interface is
559 implemented in DebuggerPluginPrivate.
563 \class Debugger::Internal::DebuggerPluginPrivate
565 Implementation of DebuggerCore.
568 class DebuggerPluginPrivate : public DebuggerCore
573 explicit DebuggerPluginPrivate(DebuggerPlugin *plugin);
574 ~DebuggerPluginPrivate();
576 bool initialize(const QStringList &arguments, QString *errorMessage);
577 void extensionsInitialized();
578 void aboutToShutdown();
580 void connectEngine(DebuggerEngine *engine);
581 void disconnectEngine() { connectEngine(0); }
582 DebuggerEngine *currentEngine() const { return m_currentEngine; }
583 DebuggerEngine *dummyEngine();
585 void setThreads(const QStringList &list, int index)
587 const bool state = m_threadBox->blockSignals(true);
588 m_threadBox->clear();
589 foreach (const QString &item, list)
590 m_threadBox->addItem(item);
591 m_threadBox->setCurrentIndex(index);
592 m_threadBox->blockSignals(state);
598 m_debuggerSettings->writeSettings();
599 m_mainWindow->writeSettings();
602 void selectThread(int index)
604 currentEngine()->selectThread(index);
607 void breakpointSetMarginActionTriggered()
609 const QAction *action = qobject_cast<const QAction *>(sender());
610 QTC_ASSERT(action, return);
611 const BreakpointMenuContextData data =
612 action->data().value<BreakpointMenuContextData>();
614 if (data.mode == BreakpointMenuContextData::MessageTracePoint) {
616 //: Message tracepoint: Address hit.
617 message = tr("0x%1 hit").arg(data.address, 0, 16);
619 //: Message tracepoint: %1 file, %2 line %3 function hit.
620 message = tr("%1:%2 %3() hit").arg(QFileInfo(data.fileName).fileName()).
621 arg(data.lineNumber).
622 arg(cppFunctionAt(data.fileName, data.lineNumber));
624 QInputDialog dialog; // Create wide input dialog.
625 dialog.setWindowFlags(dialog.windowFlags()
626 & ~(Qt::WindowContextHelpButtonHint|Qt::MSWindowsFixedSizeDialogHint));
627 dialog.resize(600, dialog.height());
628 dialog.setWindowTitle(tr("Add Message Tracepoint"));
629 dialog.setLabelText (tr("Message:"));
630 dialog.setTextValue(message);
631 if (dialog.exec() != QDialog::Accepted || dialog.textValue().isEmpty())
633 message = dialog.textValue();
636 toggleBreakpointByAddress(data.address, message);
638 toggleBreakpointByFileAndLine(data.fileName, data.lineNumber, message);
641 void breakpointRemoveMarginActionTriggered()
643 const QAction *act = qobject_cast<QAction *>(sender());
644 QTC_ASSERT(act, return);
645 BreakpointModelId id = act->data().value<BreakpointModelId>();
646 m_breakHandler->removeBreakpoint(id);
649 void breakpointEnableMarginActionTriggered()
651 const QAction *act = qobject_cast<QAction *>(sender());
652 QTC_ASSERT(act, return);
653 BreakpointModelId id = act->data().value<BreakpointModelId>();
654 breakHandler()->setEnabled(id, true);
657 void breakpointDisableMarginActionTriggered()
659 const QAction *act = qobject_cast<QAction *>(sender());
660 QTC_ASSERT(act, return);
661 BreakpointModelId id = act->data().value<BreakpointModelId>();;
662 breakHandler()->setEnabled(id, false);
665 void updateWatchersHeader(int section, int, int newSize)
667 m_watchersWindow->header()->resizeSection(section, newSize);
670 void sourceFilesDockToggled(bool on)
672 if (on && m_currentEngine->state() == InferiorStopOk)
673 m_currentEngine->reloadSourceFiles();
676 void modulesDockToggled(bool on)
678 if (on && m_currentEngine->state() == InferiorStopOk)
679 m_currentEngine->reloadModules();
682 void registerDockToggled(bool on)
684 if (on && m_currentEngine->state() == InferiorStopOk)
685 m_currentEngine->reloadRegisters();
688 void synchronizeBreakpoints()
690 showMessage("ATTEMPT SYNC", LogDebug);
691 for (int i = 0, n = m_snapshotHandler->size(); i != n; ++i) {
692 if (DebuggerEngine *engine = m_snapshotHandler->at(i))
693 engine->attemptBreakpointSynchronization();
697 void synchronizeWatchers()
699 for (int i = 0, n = m_snapshotHandler->size(); i != n; ++i) {
700 if (DebuggerEngine *engine = m_snapshotHandler->at(i))
701 engine->watchHandler()->updateWatchers();
705 void editorOpened(Core::IEditor *editor);
706 void updateBreakMenuItem(Core::IEditor *editor);
707 void setBusyCursor(bool busy);
708 void requestMark(TextEditor::ITextEditor *editor, int lineNumber);
709 void requestContextMenu(TextEditor::ITextEditor *editor,
710 int lineNumber, QMenu *menu);
712 void activatePreviousMode();
713 void activateDebugMode();
714 void toggleBreakpoint();
715 void toggleBreakpointByFileAndLine(const QString &fileName, int lineNumber,
716 const QString &tracePointMessage = QString());
717 void toggleBreakpointByAddress(quint64 address,
718 const QString &tracePointMessage = QString());
719 void onModeChanged(Core::IMode *mode);
720 void onCoreAboutToOpen();
721 void showSettingsDialog();
724 void debugProjectBreakMain();
725 void startExternalApplication();
726 void startRemoteCdbSession();
727 void startRemoteApplication();
728 bool queryRemoteParameters(DebuggerStartParameters &sp, bool useScript);
729 void attachRemoteApplication();
730 void attachToQmlPort();
731 void startRemoteEngine();
732 void attachExternalApplication();
733 Q_SLOT void attachExternalApplication(ProjectExplorer::RunControl *rc);
736 void attachRemote(const QString &spec);
738 void enableReverseDebuggingTriggered(const QVariant &value);
739 void languagesChanged();
740 void showStatusMessage(const QString &msg, int timeout = -1);
741 void openMemoryEditor();
743 const CPlusPlus::Snapshot &cppCodeModelSnapshot() const;
745 void showQtDumperLibraryWarning(const QString &details);
746 DebuggerMainWindow *mainWindow() const { return m_mainWindow; }
747 bool isDockVisible(const QString &objectName) const
748 { return mainWindow()->isDockVisible(objectName); }
750 bool hasSnapshots() const { return m_snapshotHandler->size(); }
751 void createNewDock(QWidget *widget);
753 void runControlStarted(DebuggerEngine *engine);
754 void runControlFinished(DebuggerEngine *engine);
755 DebuggerLanguages activeLanguages() const;
756 unsigned enabledEngines() const { return m_cmdLineEnabledEngines; }
757 QString debuggerForAbi(const Abi &abi, DebuggerEngineType et = NoEngineType) const;
758 void remoteCommand(const QStringList &options, const QStringList &);
760 bool isReverseDebugging() const;
762 BreakHandler *breakHandler() const { return m_breakHandler; }
763 SnapshotHandler *snapshotHandler() const { return m_snapshotHandler; }
765 void setConfigValue(const QString &name, const QVariant &value);
766 QVariant configValue(const QString &name) const;
768 DebuggerRunControl *createDebugger(const DebuggerStartParameters &sp,
769 RunConfiguration *rc = 0);
770 void startDebugger(RunControl *runControl);
771 void displayDebugger(DebuggerEngine *engine, bool updateEngine = true);
775 void setInitialState();
777 void fontSettingsChanged(const TextEditor::FontSettings &settings);
779 void updateState(DebuggerEngine *engine);
780 void updateWatchersWindow();
781 void onCurrentProjectChanged(ProjectExplorer::Project *project);
783 void sessionLoaded();
784 void aboutToUnloadSession();
785 void aboutToSaveSession();
787 void executeDebuggerCommand(const QString &command);
788 void scriptExpressionEntered(const QString &expression);
792 void updateDebugActions();
794 void handleExecDetach()
796 currentEngine()->resetLocation();
797 currentEngine()->detachDebugger();
800 void handleExecContinue()
802 currentEngine()->resetLocation();
803 currentEngine()->continueInferior();
806 void handleExecInterrupt()
808 currentEngine()->resetLocation();
809 currentEngine()->requestInterruptInferior();
812 void handleExecReset()
814 currentEngine()->resetLocation();
815 currentEngine()->notifyEngineIll(); // FIXME: Check.
818 void handleExecStep()
820 if (currentEngine()->state() == DebuggerNotReady) {
821 debugProjectBreakMain();
823 currentEngine()->resetLocation();
824 if (boolSetting(OperateByInstruction))
825 currentEngine()->executeStepI();
827 currentEngine()->executeStep();
831 void handleExecNext()
833 if (currentEngine()->state() == DebuggerNotReady) {
834 debugProjectBreakMain();
836 currentEngine()->resetLocation();
837 if (boolSetting(OperateByInstruction))
838 currentEngine()->executeNextI();
840 currentEngine()->executeNext();
844 void handleExecStepOut()
846 currentEngine()->resetLocation();
847 currentEngine()->executeStepOut();
850 void handleExecReturn()
852 currentEngine()->resetLocation();
853 currentEngine()->executeReturn();
856 void handleExecJumpToLine()
859 currentEngine()->resetLocation();
861 if (currentTextEditorPosition(&data))
862 currentEngine()->executeJumpToLine(data);
865 void handleExecRunToLine()
868 currentEngine()->resetLocation();
870 if (currentTextEditorPosition(&data))
871 currentEngine()->executeRunToLine(data);
874 void handleExecRunToSelectedFunction()
876 ITextEditor *textEditor = currentTextEditor();
877 QTC_ASSERT(textEditor, return);
878 QPlainTextEdit *ed = qobject_cast<QPlainTextEdit*>(textEditor->widget());
881 QTextCursor cursor = ed->textCursor();
882 QString functionName = cursor.selectedText();
883 if (functionName.isEmpty()) {
884 const QTextBlock block = cursor.block();
885 const QString line = block.text();
886 foreach (const QString &str, line.trimmed().split('(')) {
888 for (int i = str.size(); --i >= 0; ) {
889 if (!str.at(i).isLetterOrNumber())
900 if (functionName.isEmpty()) {
901 showStatusMessage(tr("No function selected."));
903 showStatusMessage(tr("Running to function \"%1\".")
905 currentEngine()->resetLocation();
906 currentEngine()->executeRunToFunction(functionName);
910 void slotEditBreakpoint()
912 const QAction *act = qobject_cast<QAction *>(sender());
913 QTC_ASSERT(act, return);
914 const BreakpointModelId id = act->data().value<BreakpointModelId>();
915 QTC_ASSERT(id > 0, return);
916 BreakWindow::editBreakpoint(id, mainWindow());
921 const QAction *action = qobject_cast<const QAction *>(sender());
922 QTC_ASSERT(action, return);
923 const BreakpointMenuContextData data = action->data().value<BreakpointMenuContextData>();
924 currentEngine()->executeRunToLine(data);
927 void slotJumpToLine()
929 const QAction *action = qobject_cast<const QAction *>(sender());
930 QTC_ASSERT(action, return);
931 const BreakpointMenuContextData data = action->data().value<BreakpointMenuContextData>();
932 currentEngine()->executeJumpToLine(data);
935 void handleAddToWatchWindow()
937 // Requires a selection, but that's the only case we want anyway.
938 EditorManager *editorManager = EditorManager::instance();
941 IEditor *editor = editorManager->currentEditor();
944 ITextEditor *textEditor = qobject_cast<ITextEditor*>(editor);
948 QPlainTextEdit *ptEdit = qobject_cast<QPlainTextEdit*>(editor->widget());
950 tc = ptEdit->textCursor();
952 if (tc.hasSelection()) {
953 exp = tc.selectedText();
956 exp = cppExpressionAt(textEditor, tc.position(), &line, &column);
960 currentEngine()->watchHandler()->watchExpression(exp);
963 void handleExecExit()
965 currentEngine()->exitDebugger();
968 void handleFrameDown()
970 currentEngine()->frameDown();
975 currentEngine()->frameUp();
978 void handleOperateByInstructionTriggered(bool operateByInstructionTriggered)
980 // Go to source only if we have the file.
981 if (currentEngine()->stackHandler()->currentIndex() >= 0) {
982 const StackFrame frame = currentEngine()->stackHandler()->currentFrame();
983 if (operateByInstructionTriggered || frame.isUsable()) {
984 currentEngine()->gotoLocation(Location(frame, true));
989 bool isActiveDebugLanguage(int lang) const
991 return m_mainWindow->activeDebugLanguages() & lang;
994 QVariant sessionValue(const QString &name);
995 void setSessionValue(const QString &name, const QVariant &value);
996 QIcon locationMarkIcon() const { return m_locationMarkIcon; }
998 void openTextEditor(const QString &titlePattern0, const QString &contents);
999 void clearCppCodeModelSnapshot();
1000 void showMessage(const QString &msg, int channel, int timeout = -1);
1002 Utils::SavedAction *action(int code) const;
1003 bool boolSetting(int code) const;
1004 QString stringSetting(int code) const;
1006 void showModuleSymbols(const QString &moduleName, const Symbols &symbols);
1008 bool parseArgument(QStringList::const_iterator &it,
1009 const QStringList::const_iterator &cend,
1010 unsigned *enabledEngines, QString *errorMessage);
1011 bool parseArguments(const QStringList &args,
1012 unsigned *enabledEngines, QString *errorMessage);
1014 DebuggerToolTipManager *toolTipManager() const { return m_toolTipManager; }
1015 virtual QSharedPointer<GlobalDebuggerOptions> globalDebuggerOptions() const { return m_globalDebuggerOptions; }
1018 void maybeEnrichParameters(DebuggerStartParameters *sp);
1021 DebuggerMainWindow *m_mainWindow;
1022 DebuggerRunControlFactory *m_debuggerRunControlFactory;
1024 QString m_previousMode;
1025 QList<DebuggerStartParameters> m_scheduledStarts;
1027 Utils::ProxyAction *m_visibleStartAction;
1028 Utils::ProxyAction *m_hiddenStopAction;
1029 QAction *m_startAction;
1030 QAction *m_startExternalAction;
1031 QAction *m_startRemoteAction;
1032 QAction *m_attachToQmlPortAction;
1033 QAction *m_attachRemoteAction;
1034 QAction *m_startRemoteCdbAction;
1035 QAction *m_startRemoteLldbAction;
1036 QAction *m_attachExternalAction;
1037 QAction *m_attachCoreAction;
1038 QAction *m_detachAction;
1039 QAction *m_continueAction;
1040 QAction *m_exitAction; // On application output button if "Stop" is possible
1041 QAction *m_interruptAction; // On the fat debug button if "Pause" is possible
1042 QAction *m_undisturbableAction; // On the fat debug button if nothing can be done
1043 QAction *m_resetAction;
1044 QAction *m_stepAction;
1045 QAction *m_stepOutAction;
1046 QAction *m_runToLineAction; // In the debug menu
1047 QAction *m_runToSelectedFunctionAction;
1048 QAction *m_jumpToLineAction; // In the Debug menu.
1049 QAction *m_returnFromFunctionAction;
1050 QAction *m_nextAction;
1051 QAction *m_watchAction1; // In the Debug menu.
1052 QAction *m_watchAction2; // In the text editor context menu.
1053 QAction *m_breakAction;
1054 QAction *m_reverseDirectionAction;
1055 QAction *m_frameUpAction;
1056 QAction *m_frameDownAction;
1058 QToolButton *m_reverseToolButton;
1062 QIcon m_continueIcon;
1063 QIcon m_interruptIcon;
1064 QIcon m_locationMarkIcon;
1066 Utils::StatusLabel *m_statusLabel;
1067 QComboBox *m_threadBox;
1069 BreakWindow *m_breakWindow;
1070 BreakHandler *m_breakHandler;
1071 //ConsoleWindow *m_consoleWindow;
1072 QTreeView *m_returnWindow;
1073 QTreeView *m_localsWindow;
1074 QTreeView *m_watchersWindow;
1075 QAbstractItemView *m_registerWindow;
1076 QAbstractItemView *m_modulesWindow;
1077 QAbstractItemView *m_snapshotWindow;
1078 SourceFilesWindow *m_sourceFilesWindow;
1079 QAbstractItemView *m_stackWindow;
1080 QAbstractItemView *m_threadsWindow;
1081 LogWindow *m_logWindow;
1082 ScriptConsole *m_scriptConsoleWindow;
1085 QString m_lastPermanentStatusMessage;
1087 mutable CPlusPlus::Snapshot m_codeModelSnapshot;
1088 DebuggerPlugin *m_plugin;
1090 SnapshotHandler *m_snapshotHandler;
1091 bool m_shuttingDown;
1092 DebuggerEngine *m_currentEngine;
1093 DebuggerSettings *m_debuggerSettings;
1094 QSettings *m_coreSettings;
1095 bool m_gdbBinariesChanged;
1096 uint m_cmdLineEnabledEngines;
1097 QStringList m_arguments;
1098 DebuggerToolTipManager *m_toolTipManager;
1099 CommonOptionsPage *m_commonOptionsPage;
1100 DummyEngine *m_dummyEngine;
1101 const QSharedPointer<GlobalDebuggerOptions> m_globalDebuggerOptions;
1104 DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin) :
1105 m_toolTipManager(new DebuggerToolTipManager(this)),
1107 m_globalDebuggerOptions(new GlobalDebuggerOptions)
1109 setObjectName("DebuggerCore");
1110 qRegisterMetaType<WatchData>("WatchData");
1111 qRegisterMetaType<ContextData>("ContextData");
1112 qRegisterMetaType<DebuggerStartParameters>("DebuggerStartParameters");
1114 QTC_CHECK(!theDebuggerCore);
1115 theDebuggerCore = this;
1119 m_startRemoteCdbAction = 0;
1120 m_shuttingDown = false;
1128 m_watchersWindow = 0;
1129 m_registerWindow = 0;
1130 m_modulesWindow = 0;
1131 m_snapshotWindow = 0;
1132 m_sourceFilesWindow = 0;
1134 m_threadsWindow = 0;
1136 m_scriptConsoleWindow = 0;
1139 m_snapshotHandler = 0;
1140 m_currentEngine = 0;
1141 m_debuggerSettings = 0;
1143 m_gdbBinariesChanged = true;
1144 m_cmdLineEnabledEngines = AllEngineTypes;
1146 m_reverseToolButton = 0;
1148 m_startExternalAction = 0;
1149 m_startRemoteAction = 0;
1150 m_attachRemoteAction = 0;
1151 m_attachToQmlPortAction = 0;
1152 m_startRemoteCdbAction = 0;
1153 m_startRemoteLldbAction = 0;
1154 m_attachExternalAction = 0;
1155 m_attachCoreAction = 0;
1158 m_commonOptionsPage = 0;
1161 DebuggerPluginPrivate::~DebuggerPluginPrivate()
1163 delete m_debuggerSettings;
1164 m_debuggerSettings = 0;
1166 // Mainwindow will be deleted by debug mode.
1168 delete m_snapshotHandler;
1169 m_snapshotHandler = 0;
1171 delete m_breakHandler;
1175 DebuggerEngine *DebuggerPluginPrivate::dummyEngine()
1177 if (!m_dummyEngine) {
1178 m_dummyEngine = new DummyEngine;
1179 m_dummyEngine->setParent(this);
1180 m_dummyEngine->setObjectName(_("DummyEngine"));
1182 return m_dummyEngine;
1185 DebuggerCore *debuggerCore()
1187 return theDebuggerCore;
1190 static QString msgParameterMissing(const QString &a)
1192 return DebuggerPlugin::tr("Option '%1' is missing the parameter.").arg(a);
1195 void DebuggerPluginPrivate::maybeEnrichParameters(DebuggerStartParameters *sp)
1197 if (!boolSetting(AutoEnrichParameters))
1199 if (sp->sysroot.isEmpty() && (sp->startMode == AttachToRemoteServer
1200 || sp->startMode == StartRemote)) {
1201 // FIXME: Get from BaseQtVersion.
1202 sp->sysroot = QString::fromLocal8Bit(qgetenv("QTC_DEBUGGER_SYSROOT"));
1203 showMessage(QString::fromLatin1("USING QTC_DEBUGGER_SYSROOT %1")
1204 .arg(sp->sysroot), LogWarning);
1206 if (sp->debugInfoLocation.isEmpty())
1207 sp->debugInfoLocation = sp->sysroot + "/usr/lib/debug";
1208 if (sp->debugSourceLocation.isEmpty()) {
1209 QString base = sp->sysroot + "/usr/src/debug/";
1210 sp->debugSourceLocation.append(base + "qt5base/src/corelib");
1211 sp->debugSourceLocation.append(base + "qt5base/src/gui");
1212 sp->debugSourceLocation.append(base + "qt5base/src/network");
1213 sp->debugSourceLocation.append(base + "qt5base/src/v8");
1214 sp->debugSourceLocation.append(base + "qtdeclarative/src/declarative/qml");
1218 bool DebuggerPluginPrivate::parseArgument(QStringList::const_iterator &it,
1219 const QStringList::const_iterator &cend,
1220 unsigned *enabledEngines, QString *errorMessage)
1222 const QString &option = *it;
1224 // '-debug <corefile>'
1225 // '-debug <server:port>@<exe>@<arch>'
1226 if (*it == _("-debug")) {
1229 *errorMessage = msgParameterMissing(*it);
1232 DebuggerStartParameters sp;
1233 qulonglong pid = it->toULongLong();
1234 QString remoteChannel = it->contains('@') ? it->section('@', 0, 0) : *it;
1236 int pos = remoteChannel.indexOf(QLatin1Char(':'));
1238 port = remoteChannel.mid(pos + 1).toUInt();
1240 sp.startMode = AttachExternal;
1242 sp.displayName = tr("Process %1").arg(sp.attachPID);
1243 sp.startMessage = tr("Attaching to local process %1.").arg(sp.attachPID);
1244 sp.toolChainAbi = Abi::hostAbi();
1246 sp.startMode = AttachToRemoteServer;
1247 sp.remoteChannel = remoteChannel;
1248 sp.executable = it->section('@', 1, 1);
1249 if (sp.remoteChannel.isEmpty()) {
1250 *errorMessage = DebuggerPlugin::tr("The parameter '%1' of option "
1251 "'%2' does not match the pattern <server:port>@<executable>@<architecture>.")
1255 sp.remoteArchitecture = it->section('@', 2, 2);
1256 sp.displayName = tr("Remote: \"%1\"").arg(sp.remoteChannel);
1257 sp.startMessage = tr("Attaching to remote server %1.")
1258 .arg(sp.remoteChannel);
1259 sp.toolChainAbi = anyAbiOfBinary(sp.executable);
1261 // Fixme: Distinguish between core-file and executable by argument syntax?
1262 // (default up to 2.2 was core-file (".dmp on Windows)).
1263 const bool isExecutable = Abi::hostAbi().os() == Abi::WindowsOS ?
1264 !it->endsWith(QLatin1String(".dmp"), Qt::CaseInsensitive) :
1265 QFileInfo(*it).isExecutable();
1267 sp.startMode = StartExternal;
1268 sp.executable = *it;
1269 sp.displayName = tr("Executable file \"%1\"").arg(sp.executable);
1270 sp.startMessage = tr("Debugging file %1.").arg(sp.executable);
1272 sp.startMode = AttachCore;
1274 sp.displayName = tr("Core file \"%1\"").arg(sp.coreFile);
1275 sp.startMessage = tr("Attaching to core file %1.").arg(sp.coreFile);
1277 sp.toolChainAbi = anyAbiOfBinary(*it);
1279 m_scheduledStarts.append(sp);
1282 // -wincrashevent <event-handle>:<pid>. A handle used for
1283 // a handshake when attaching to a crashed Windows process.
1284 // This is created by $QTC/src/tools/qtcdebugger/main.cpp:
1285 // args << QLatin1String("-wincrashevent")
1286 // << QString("%1:%2").arg(argWinCrashEvent).arg(argProcessId);
1287 if (*it == _("-wincrashevent")) {
1290 *errorMessage = msgParameterMissing(*it);
1293 DebuggerStartParameters sp;
1294 sp.startMode = AttachCrashedExternal;
1295 sp.crashParameter = it->section(':', 0, 0);
1296 sp.attachPID = it->section(':', 1, 1).toULongLong();
1297 sp.displayName = tr("Crashed process %1").arg(sp.attachPID);
1298 sp.startMessage = tr("Attaching to crashed process %1").arg(sp.attachPID);
1299 sp.toolChainAbi = Abi::hostAbi();
1300 if (!sp.attachPID) {
1301 *errorMessage = DebuggerPlugin::tr("The parameter '%1' of option '%2' "
1302 "does not match the pattern <handle>:<pid>.").arg(*it, option);
1305 m_scheduledStarts.append(sp);
1308 // Engine disabling.
1309 if (option == _("-disable-cdb")) {
1310 *enabledEngines &= ~CdbEngineType;
1313 if (option == _("-disable-gdb")) {
1314 *enabledEngines &= ~GdbEngineType;
1317 if (option == _("-disable-qmldb")) {
1318 *enabledEngines &= ~QmlEngineType;
1321 if (option == _("-disable-sdb")) {
1322 *enabledEngines &= ~ScriptEngineType;
1325 if (option == _("-disable-lldb")) {
1326 *enabledEngines &= ~LldbEngineType;
1330 *errorMessage = DebuggerPlugin::tr("Invalid debugger option: %1").arg(option);
1334 bool DebuggerPluginPrivate::parseArguments(const QStringList &args,
1335 unsigned *enabledEngines, QString *errorMessage)
1337 const QStringList::const_iterator cend = args.constEnd();
1338 for (QStringList::const_iterator it = args.constBegin(); it != cend; ++it)
1339 if (!parseArgument(it, cend, enabledEngines, errorMessage))
1341 if (Constants::Internal::debug)
1342 qDebug().nospace() << args << "engines=0x"
1343 << QString::number(*enabledEngines, 16) << '\n';
1347 bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
1348 QString *errorMessage)
1350 Q_UNUSED(errorMessage);
1351 m_arguments = arguments;
1353 m_mainWindow = new DebuggerMainWindow;
1358 void DebuggerPluginPrivate::setConfigValue(const QString &name, const QVariant &value)
1360 m_coreSettings->setValue(_("DebugMode/") + name, value);
1363 QVariant DebuggerPluginPrivate::configValue(const QString &name) const
1365 const QVariant value = m_coreSettings->value(_("DebugMode/") + name);
1366 if (value.isValid())
1368 // Legacy (pre-2.1): Check old un-namespaced-settings.
1369 return m_coreSettings->value(name);
1372 void DebuggerPluginPrivate::onCurrentProjectChanged(Project *project)
1374 RunConfiguration *activeRc = 0;
1376 Target *target = project->activeTarget();
1377 QTC_ASSERT(target, return);
1378 activeRc = target->activeRunConfiguration();
1379 QTC_CHECK(activeRc);
1381 for (int i = 0, n = m_snapshotHandler->size(); i != n; ++i) {
1382 // Run controls might be deleted during exit.
1383 if (DebuggerEngine *engine = m_snapshotHandler->at(i)) {
1384 DebuggerRunControl *runControl = engine->runControl();
1385 RunConfiguration *rc = runControl->runConfiguration();
1386 if (rc == activeRc) {
1387 m_snapshotHandler->setCurrentIndex(i);
1388 updateState(engine);
1393 // No corresponding debugger found. So we are ready to start one.
1394 m_interruptAction->setEnabled(false);
1395 m_continueAction->setEnabled(false);
1396 m_exitAction->setEnabled(false);
1397 m_startAction->setEnabled(true);
1398 m_visibleStartAction->setAction(m_startAction);
1401 void DebuggerPluginPrivate::languagesChanged()
1405 void DebuggerPluginPrivate::debugProject()
1407 ProjectExplorerPlugin *pe = ProjectExplorerPlugin::instance();
1408 if (Project *pro = pe->startupProject())
1409 pe->runProject(pro, Constants::DEBUGMODE);
1412 void DebuggerPluginPrivate::debugProjectBreakMain()
1414 ProjectExplorerPlugin *pe = ProjectExplorerPlugin::instance();
1415 if (Project *pro = pe->startupProject())
1416 pe->runProject(pro, Constants::DEBUGMODE2);
1419 void DebuggerPluginPrivate::startExternalApplication()
1421 DebuggerStartParameters sp;
1422 StartExternalDialog dlg(mainWindow());
1423 dlg.setExecutableFile(
1424 configValue(_("LastExternalExecutableFile")).toString());
1425 dlg.setExecutableArguments(
1426 configValue(_("LastExternalExecutableArguments")).toString());
1427 dlg.setRunInTerminal(
1428 configValue(_("LastExternalRunInTerminal")).toBool());
1429 dlg.setWorkingDirectory(
1430 configValue(_("LastExternalWorkingDirectory")).toString());
1431 dlg.setAbiIndex(configValue(_("LastExternalAbiIndex")).toInt());
1433 if (dlg.exec() != QDialog::Accepted)
1436 setConfigValue(_("LastExternalExecutableFile"),
1437 dlg.executableFile());
1438 setConfigValue(_("LastExternalExecutableArguments"),
1439 dlg.executableArguments());
1440 setConfigValue(_("LastExternalWorkingDirectory"),
1441 dlg.workingDirectory());
1442 setConfigValue(_("LastExternalRunInTerminal"),
1443 dlg.runInTerminal());
1444 setConfigValue(_("LastExternalAbiIndex"), QVariant(dlg.abiIndex()));
1446 sp.executable = dlg.executableFile();
1447 sp.startMode = StartExternal;
1448 sp.toolChainAbi = dlg.abi();
1449 sp.debuggerCommand = dlg.debuggerCommand();
1450 sp.workingDirectory = dlg.workingDirectory();
1451 sp.displayName = sp.executable;
1452 sp.useTerminal = dlg.runInTerminal();
1453 if (!dlg.executableArguments().isEmpty())
1454 sp.processArgs = dlg.executableArguments();
1455 // Fixme: 1 of 3 testing hacks.
1456 if (sp.processArgs.startsWith(__("@tcf@ ")) || sp.processArgs.startsWith(__("@sym@ ")))
1457 // Set up an ARM Symbian Abi
1458 sp.toolChainAbi = Abi(Abi::ArmArchitecture, Abi::SymbianOS, Abi::SymbianDeviceFlavor, Abi::ElfFormat, false);
1460 sp.breakOnMain = dlg.breakAtMain();
1461 if (RunControl *rc = m_debuggerRunControlFactory->create(sp))
1465 void DebuggerPluginPrivate::attachExternalApplication()
1467 AttachExternalDialog dlg(mainWindow());
1468 dlg.setAbiIndex(configValue(_("LastAttachExternalAbiIndex")).toInt());
1470 if (dlg.exec() != QDialog::Accepted)
1473 if (dlg.attachPID() == 0) {
1474 QMessageBox::warning(mainWindow(), tr("Warning"),
1475 tr("Cannot attach to process with PID 0"));
1479 setConfigValue(_("LastAttachExternalAbiIndex"), QVariant(dlg.abiIndex()));
1481 DebuggerStartParameters sp;
1482 sp.attachPID = dlg.attachPID();
1483 sp.displayName = tr("Process %1").arg(dlg.attachPID());
1484 sp.executable = dlg.executable();
1485 sp.startMode = AttachExternal;
1486 sp.toolChainAbi = dlg.abi();
1487 sp.debuggerCommand = dlg.debuggerCommand();
1488 if (DebuggerRunControl *rc = createDebugger(sp))
1492 void DebuggerPluginPrivate::attachExternalApplication(ProjectExplorer::RunControl *rc)
1494 DebuggerStartParameters sp;
1495 sp.attachPID = rc->applicationProcessHandle().pid();
1496 sp.displayName = tr("Debugger attached to %1").arg(rc->displayName());
1497 sp.startMode = AttachExternal;
1498 sp.toolChainAbi = rc->abi();
1499 if (DebuggerRunControl *rc = createDebugger(sp))
1503 void DebuggerPluginPrivate::attachCore()
1505 AttachCoreDialog dlg(mainWindow());
1506 dlg.setExecutableFile(configValue(_("LastExternalExecutableFile")).toString());
1507 dlg.setCoreFile(configValue(_("LastExternalCoreFile")).toString());
1508 dlg.setAbiIndex(configValue(_("LastExternalCoreAbiIndex")).toInt());
1509 dlg.setSysroot(configValue(_("LastSysroot")).toString());
1510 dlg.setOverrideStartScript(configValue(_("LastExternalStartScript")).toString());
1512 if (dlg.exec() != QDialog::Accepted)
1515 setConfigValue(_("LastExternalExecutableFile"), dlg.executableFile());
1516 setConfigValue(_("LastExternalCoreFile"), dlg.coreFile());
1517 setConfigValue(_("LastExternalCoreAbiIndex"), QVariant(dlg.abiIndex()));
1518 setConfigValue(_("LastSysroot"), dlg.sysroot());
1519 setConfigValue(_("LastExternalStartScript"), dlg.overrideStartScript());
1521 DebuggerStartParameters sp;
1522 sp.executable = dlg.executableFile();
1523 sp.coreFile = dlg.coreFile();
1524 sp.displayName = tr("Core file \"%1\"").arg(dlg.coreFile());
1525 sp.startMode = AttachCore;
1526 sp.debuggerCommand = dlg.debuggerCommand();
1527 sp.toolChainAbi = dlg.abi();
1528 sp.sysroot = dlg.sysroot();
1529 sp.overrideStartScript = dlg.overrideStartScript();
1530 if (DebuggerRunControl *rc = createDebugger(sp))
1534 void DebuggerPluginPrivate::attachRemote(const QString &spec)
1536 // spec is: server:port@executable@architecture
1537 DebuggerStartParameters sp;
1538 sp.remoteChannel = spec.section('@', 0, 0);
1539 sp.executable = spec.section('@', 1, 1);
1540 sp.remoteArchitecture = spec.section('@', 2, 2);
1541 sp.displayName = tr("Remote: \"%1\"").arg(sp.remoteChannel);
1542 sp.startMode = AttachToRemoteServer;
1543 sp.toolChainAbi = anyAbiOfBinary(sp.executable);
1544 if (DebuggerRunControl *rc = createDebugger(sp))
1548 void DebuggerPluginPrivate::startRemoteCdbSession()
1550 const QString connectionKey = _("CdbRemoteConnection");
1551 DebuggerStartParameters sp;
1552 Abi hostAbi = Abi::hostAbi();
1553 sp.toolChainAbi = ProjectExplorer::Abi(hostAbi.architecture(),
1554 ProjectExplorer::Abi::WindowsOS,
1555 ProjectExplorer::Abi::WindowsMsvc2010Flavor,
1556 ProjectExplorer::Abi::PEFormat,
1557 hostAbi.wordWidth());
1558 sp.startMode = AttachToRemoteServer;
1559 StartRemoteCdbDialog dlg(mainWindow());
1560 QString previousConnection = configValue(connectionKey).toString();
1561 if (previousConnection.isEmpty())
1562 previousConnection = QLatin1String("localhost:1234");
1563 dlg.setConnection(previousConnection);
1564 if (dlg.exec() != QDialog::Accepted)
1566 sp.remoteChannel = dlg.connection();
1567 setConfigValue(connectionKey, sp.remoteChannel);
1568 if (RunControl *rc = createDebugger(sp))
1572 bool DebuggerPluginPrivate::queryRemoteParameters(DebuggerStartParameters &sp, bool useScript)
1574 StartRemoteDialog dlg(mainWindow(), useScript);
1576 arches.append(_("i386:x86-64:intel"));
1577 arches.append(_("i386"));
1578 arches.append(_("arm"));
1579 QString lastUsed = configValue(_("LastRemoteArchitecture")).toString();
1580 if (!arches.contains(lastUsed))
1581 arches.prepend(lastUsed);
1582 dlg.setRemoteArchitectures(arches);
1583 QStringList gnuTargets;
1584 gnuTargets.append(_("auto"));
1585 gnuTargets.append(_("i686-linux-gnu"));
1586 gnuTargets.append(_("x86_64-linux-gnu"));
1587 gnuTargets.append(_("arm-none-linux-gnueabi"));
1588 const QString lastUsedGnuTarget
1589 = configValue(_("LastGnuTarget")).toString();
1590 if (!gnuTargets.contains(lastUsedGnuTarget))
1591 gnuTargets.prepend(lastUsedGnuTarget);
1592 dlg.setGnuTargets(gnuTargets);
1593 dlg.setRemoteChannel(
1594 configValue(_("LastRemoteChannel")).toString());
1595 dlg.setLocalExecutable(
1596 configValue(_("LastLocalExecutable")).toString());
1597 dlg.setDebugger(configValue(_("LastDebugger")).toString());
1598 dlg.setRemoteArchitecture(lastUsed);
1599 dlg.setGnuTarget(lastUsedGnuTarget);
1600 dlg.setOverrideStartScript(configValue(_("LastRemoteStartScript")).toString());
1601 dlg.setServerStartScript(
1602 configValue(_("LastServerStartScript")).toString());
1603 dlg.setUseServerStartScript(
1604 configValue(_("LastUseServerStartScript")).toBool());
1605 dlg.setSysroot(configValue(_("LastSysroot")).toString());
1606 dlg.setDebugInfoLocation(configValue(_("LastDebugInfoLocation")).toString());
1607 if (dlg.exec() != QDialog::Accepted)
1609 setConfigValue(_("LastRemoteChannel"), dlg.remoteChannel());
1610 setConfigValue(_("LastLocalExecutable"), dlg.localExecutable());
1611 setConfigValue(_("LastDebugger"), dlg.debugger());
1612 setConfigValue(_("LastRemoteArchitecture"), dlg.remoteArchitecture());
1613 setConfigValue(_("LastGnuTarget"), dlg.gnuTarget());
1614 setConfigValue(_("LastRemoteStartScript"), dlg.overrideStartScript());
1615 setConfigValue(_("LastServerStartScript"), dlg.serverStartScript());
1616 setConfigValue(_("LastUseServerStartScript"), dlg.useServerStartScript());
1617 setConfigValue(_("LastSysroot"), dlg.sysroot());
1618 setConfigValue(_("LastDebugInfoLocation"), dlg.debugInfoLocation());
1619 sp.remoteChannel = dlg.remoteChannel();
1620 sp.remoteArchitecture = dlg.remoteArchitecture();
1621 sp.gnuTarget = dlg.gnuTarget();
1622 sp.executable = dlg.localExecutable();
1623 sp.displayName = tr("Remote: \"%1\"").arg(sp.remoteChannel);
1624 sp.debuggerCommand = dlg.debugger(); // Override toolchain-detection.
1625 if (!sp.debuggerCommand.isEmpty())
1626 sp.toolChainAbi = ProjectExplorer::Abi();
1627 sp.overrideStartScript = dlg.overrideStartScript();
1628 sp.useServerStartScript = dlg.useServerStartScript();
1629 sp.serverStartScript = dlg.serverStartScript();
1630 sp.sysroot = dlg.sysroot();
1631 sp.debugInfoLocation = dlg.debugInfoLocation();
1635 void DebuggerPluginPrivate::startRemoteApplication()
1637 DebuggerStartParameters sp;
1638 sp.startMode = StartRemote;
1639 if (!queryRemoteParameters(sp, true))
1641 if (RunControl *rc = createDebugger(sp))
1645 void DebuggerPluginPrivate::attachRemoteApplication()
1647 DebuggerStartParameters sp;
1648 if (!queryRemoteParameters(sp, false))
1650 sp.startMode = AttachToRemoteServer;
1651 sp.useServerStartScript = false;
1652 sp.serverStartScript.clear();
1653 if (RunControl *rc = createDebugger(sp))
1657 void DebuggerPluginPrivate::attachToQmlPort()
1659 DebuggerStartParameters sp;
1660 AttachToQmlPortDialog dlg(mainWindow());
1662 const QVariant qmlServerAddress = configValue(_("LastQmlServerAddress"));
1663 if (qmlServerAddress.isValid()) {
1664 dlg.setHost(qmlServerAddress.toString());
1666 dlg.setHost(sp.qmlServerAddress);
1669 const QVariant qmlServerPort = configValue(_("LastQmlServerPort"));
1670 if (qmlServerPort.isValid()) {
1671 dlg.setPort(qmlServerPort.toInt());
1673 dlg.setPort(sp.qmlServerPort);
1676 if (dlg.exec() != QDialog::Accepted)
1679 setConfigValue(_("LastQmlServerAddress"), dlg.host());
1680 setConfigValue(_("LastQmlServerPort"), dlg.port());
1682 sp.qmlServerAddress = dlg.host();
1683 sp.qmlServerPort = dlg.port();
1685 sp.startMode = AttachToQmlPort;
1686 if (RunControl *rc = createDebugger(sp))
1690 void DebuggerPluginPrivate::startRemoteEngine()
1692 DebuggerStartParameters sp;
1693 StartRemoteEngineDialog dlg(mainWindow());
1694 if (dlg.exec() != QDialog::Accepted)
1697 sp.connParams.host = dlg.host();
1698 sp.connParams.userName = dlg.username();
1699 sp.connParams.password = dlg.password();
1701 sp.connParams.timeout = 5;
1702 sp.connParams.authenticationType = Utils::SshConnectionParameters::AuthenticationByPassword;
1703 sp.connParams.port = 22;
1704 sp.connParams.proxyType = Utils::SshConnectionParameters::NoProxy;
1706 sp.executable = dlg.inferiorPath();
1707 sp.serverStartScript = dlg.enginePath();
1708 sp.startMode = StartRemoteEngine;
1709 if (RunControl *rc = createDebugger(sp))
1713 void DebuggerPluginPrivate::enableReverseDebuggingTriggered(const QVariant &value)
1715 QTC_ASSERT(m_reverseToolButton, return);
1716 m_reverseToolButton->setVisible(value.toBool());
1717 m_reverseDirectionAction->setChecked(false);
1718 m_reverseDirectionAction->setEnabled(value.toBool());
1721 void DebuggerPluginPrivate::runScheduled()
1723 foreach (const DebuggerStartParameters &sp, m_scheduledStarts) {
1724 RunControl *rc = createDebugger(sp);
1725 QTC_ASSERT(rc, qDebug() << "CANNOT CREATE RUN CONTROL"; continue);
1726 showStatusMessage(sp.startMessage);
1731 void DebuggerPluginPrivate::editorOpened(IEditor *editor)
1733 if (!isEditorDebuggable(editor))
1735 ITextEditor *textEditor = qobject_cast<ITextEditor *>(editor);
1739 SIGNAL(markRequested(TextEditor::ITextEditor*,int)),
1740 SLOT(requestMark(TextEditor::ITextEditor*,int)));
1742 SIGNAL(markContextMenuRequested(TextEditor::ITextEditor*,int,QMenu*)),
1743 SLOT(requestContextMenu(TextEditor::ITextEditor*,int,QMenu*)));
1746 void DebuggerPluginPrivate::updateBreakMenuItem(Core::IEditor *editor)
1748 ITextEditor *textEditor = qobject_cast<ITextEditor *>(editor);
1749 m_breakAction->setEnabled(textEditor != 0);
1752 void DebuggerPluginPrivate::requestContextMenu(ITextEditor *editor,
1753 int lineNumber, QMenu *menu)
1755 if (!isEditorDebuggable(editor))
1758 BreakpointMenuContextData args;
1759 args.lineNumber = lineNumber;
1760 bool contextUsable = true;
1762 BreakpointModelId id = BreakpointModelId();
1763 if (editor->property("DisassemblerView").toBool()) {
1764 args.fileName = editor->file()->fileName();
1765 QString line = editor->contents()
1766 .section('\n', lineNumber - 1, lineNumber - 1);
1767 BreakpointResponse needle;
1768 needle.type = BreakpointByAddress;
1769 needle.address = DisassemblerLine::addressFromDisassemblyLine(line);
1770 args.address = needle.address;
1771 needle.lineNumber = -1;
1772 id = breakHandler()->findSimilarBreakpoint(needle);
1773 contextUsable = args.address != 0;
1775 args.fileName = editor->file()->fileName();
1777 ->findBreakpointByFileAndLine(args.fileName, lineNumber);
1781 // Remove existing breakpoint.
1782 QAction *act = new QAction(menu);
1783 act->setData(QVariant::fromValue(id));
1784 act->setText(tr("Remove Breakpoint %1").arg(id.toString()));
1785 connect(act, SIGNAL(triggered()),
1786 SLOT(breakpointRemoveMarginActionTriggered()));
1787 menu->addAction(act);
1789 // Enable/disable existing breakpoint.
1790 act = new QAction(menu);
1791 act->setData(QVariant::fromValue(id));
1792 if (breakHandler()->isEnabled(id)) {
1793 act->setText(tr("Disable Breakpoint %1").arg(id.toString()));
1794 connect(act, SIGNAL(triggered()),
1795 SLOT(breakpointDisableMarginActionTriggered()));
1797 act->setText(tr("Enable Breakpoint %1").arg(id.toString()));
1798 connect(act, SIGNAL(triggered()),
1799 SLOT(breakpointEnableMarginActionTriggered()));
1801 menu->addAction(act);
1803 // Edit existing breakpoint.
1804 act = new QAction(menu);
1805 act->setText(tr("Edit Breakpoint %1...").arg(id.toString()));
1806 connect(act, SIGNAL(triggered()), SLOT(slotEditBreakpoint()));
1807 act->setData(QVariant::fromValue(id));
1808 menu->addAction(act);
1810 // Handle non-existing breakpoint.
1811 const QString text = args.address
1812 ? tr("Set Breakpoint at 0x%1").arg(args.address, 0, 16)
1813 : tr("Set Breakpoint at line %1").arg(lineNumber);
1814 QAction *act = new QAction(text, menu);
1815 act->setData(QVariant::fromValue(args));
1816 act->setEnabled(contextUsable);
1817 connect(act, SIGNAL(triggered()),
1818 SLOT(breakpointSetMarginActionTriggered()));
1819 menu->addAction(act);
1820 // Message trace point
1821 args.mode = BreakpointMenuContextData::MessageTracePoint;
1822 const QString tracePointText = args.address
1823 ? tr("Set Message Tracepoint at 0x%1...").arg(args.address, 0, 16)
1824 : tr("Set Message Tracepoint at line %1...").arg(lineNumber);
1825 act = new QAction(tracePointText, menu);
1826 act->setData(QVariant::fromValue(args));
1827 act->setEnabled(contextUsable);
1828 connect(act, SIGNAL(triggered()),
1829 SLOT(breakpointSetMarginActionTriggered()));
1830 menu->addAction(act);
1832 // Run to, jump to line below in stopped state.
1833 if (currentEngine()->state() == InferiorStopOk && contextUsable) {
1834 menu->addSeparator();
1835 if (currentEngine()->debuggerCapabilities() & RunToLineCapability) {
1836 const QString runText = args.address
1837 ? DebuggerEngine::tr("Run to Address 0x%1").arg(args.address, 0, 16)
1838 : DebuggerEngine::tr("Run to Line %1").arg(args.lineNumber);
1839 QAction *runToLineAction = new QAction(runText, menu);
1840 runToLineAction->setData(QVariant::fromValue(args));
1841 connect(runToLineAction, SIGNAL(triggered()), SLOT(slotRunToLine()));
1842 menu->addAction(runToLineAction);
1844 if (currentEngine()->debuggerCapabilities() & JumpToLineCapability) {
1845 const QString jumpText = args.address
1846 ? DebuggerEngine::tr("Jump to Address 0x%1").arg(args.address, 0, 16)
1847 : DebuggerEngine::tr("Jump to Line %1").arg(args.lineNumber);
1848 QAction *jumpToLineAction = new QAction(jumpText, menu);
1849 jumpToLineAction->setData(QVariant::fromValue(args));
1850 connect(jumpToLineAction, SIGNAL(triggered()), SLOT(slotJumpToLine()));
1851 menu->addAction(jumpToLineAction);
1856 void DebuggerPluginPrivate::toggleBreakpoint()
1858 ITextEditor *textEditor = currentTextEditor();
1859 QTC_ASSERT(textEditor, return);
1860 const int lineNumber = textEditor->currentLine();
1861 if (textEditor->property("DisassemblerView").toBool()) {
1862 QString line = textEditor->contents()
1863 .section('\n', lineNumber - 1, lineNumber - 1);
1864 quint64 address = DisassemblerLine::addressFromDisassemblyLine(line);
1865 toggleBreakpointByAddress(address);
1866 } else if (lineNumber >= 0) {
1867 toggleBreakpointByFileAndLine(textEditor->file()->fileName(), lineNumber);
1871 void DebuggerPluginPrivate::toggleBreakpointByFileAndLine(const QString &fileName,
1872 int lineNumber, const QString &tracePointMessage)
1874 BreakHandler *handler = m_breakHandler;
1875 BreakpointModelId id =
1876 handler->findBreakpointByFileAndLine(fileName, lineNumber, true);
1878 id = handler->findBreakpointByFileAndLine(fileName, lineNumber, false);
1881 handler->removeBreakpoint(id);
1883 BreakpointParameters data(BreakpointByFileAndLine);
1884 data.tracepoint = !tracePointMessage.isEmpty();
1885 data.message = tracePointMessage;
1886 data.fileName = fileName;
1887 data.lineNumber = lineNumber;
1888 handler->appendBreakpoint(data);
1892 void DebuggerPluginPrivate::toggleBreakpointByAddress(quint64 address,
1893 const QString &tracePointMessage)
1895 BreakHandler *handler = m_breakHandler;
1896 BreakpointModelId id = handler->findBreakpointByAddress(address);
1899 handler->removeBreakpoint(id);
1901 BreakpointParameters data(BreakpointByAddress);
1902 data.tracepoint = !tracePointMessage.isEmpty();
1903 data.message = tracePointMessage;
1904 data.address = address;
1905 handler->appendBreakpoint(data);
1909 void DebuggerPluginPrivate::requestMark(ITextEditor *editor, int lineNumber)
1911 if (editor->property("DisassemblerView").toBool()) {
1912 QString line = editor->contents()
1913 .section('\n', lineNumber - 1, lineNumber - 1);
1914 quint64 address = DisassemblerLine::addressFromDisassemblyLine(line);
1915 toggleBreakpointByAddress(address);
1916 } else if (editor->file()) {
1917 toggleBreakpointByFileAndLine(editor->file()->fileName(), lineNumber);
1921 DebuggerRunControl *DebuggerPluginPrivate::createDebugger
1922 (const DebuggerStartParameters &sp0, RunConfiguration *rc)
1924 DebuggerStartParameters sp = sp0;
1925 maybeEnrichParameters(&sp);
1926 return m_debuggerRunControlFactory->create(sp, rc);
1929 // If updateEngine is set, the engine will update its threads/modules and so forth.
1930 void DebuggerPluginPrivate::displayDebugger(DebuggerEngine *engine, bool updateEngine)
1932 QTC_ASSERT(engine, return);
1934 connectEngine(engine);
1936 engine->updateAll();
1937 engine->updateViews();
1940 void DebuggerPluginPrivate::startDebugger(RunControl *rc)
1942 QTC_ASSERT(rc, return);
1943 ProjectExplorerPlugin::instance()->startRunControl(rc, Constants::DEBUGMODE);
1947 void DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine)
1950 engine = dummyEngine();
1952 if (m_currentEngine == engine)
1955 if (m_currentEngine)
1956 m_currentEngine->resetLocation();
1957 m_currentEngine = engine;
1959 m_localsWindow->setModel(engine->localsModel());
1960 m_modulesWindow->setModel(engine->modulesModel());
1961 m_registerWindow->setModel(engine->registerModel());
1962 m_returnWindow->setModel(engine->returnModel());
1963 m_sourceFilesWindow->setModel(engine->sourceFilesModel());
1964 m_stackWindow->setModel(engine->stackModel());
1965 m_threadsWindow->setModel(engine->threadsModel());
1966 //m_threadBox->setModel(engine->threadsModel());
1967 //m_threadBox->setModelColumn(ThreadData::ComboNameColumn);
1968 m_watchersWindow->setModel(engine->watchersModel());
1969 engine->watchHandler()->rebuildModel();
1972 static void changeFontSize(QWidget *widget, qreal size)
1974 QFont font = widget->font();
1975 font.setPointSizeF(size);
1976 widget->setFont(font);
1979 void DebuggerPluginPrivate::fontSettingsChanged
1980 (const TextEditor::FontSettings &settings)
1982 if (!boolSetting(FontSizeFollowsEditor))
1984 qreal size = settings.fontZoom() * settings.fontSize() / 100.;
1985 changeFontSize(m_breakWindow, size);
1986 changeFontSize(m_logWindow, size);
1987 changeFontSize(m_localsWindow, size);
1988 changeFontSize(m_modulesWindow, size);
1989 //changeFontSize(m_consoleWindow, size);
1990 changeFontSize(m_registerWindow, size);
1991 changeFontSize(m_returnWindow, size);
1992 changeFontSize(m_sourceFilesWindow, size);
1993 changeFontSize(m_stackWindow, size);
1994 changeFontSize(m_threadsWindow, size);
1995 changeFontSize(m_watchersWindow, size);
1998 void DebuggerPluginPrivate::cleanupViews()
2000 m_reverseDirectionAction->setChecked(false);
2001 m_reverseDirectionAction->setEnabled(false);
2003 if (!boolSetting(CloseBuffersOnExit))
2006 EditorManager *editorManager = EditorManager::instance();
2007 QTC_ASSERT(editorManager, return);
2008 QList<IEditor *> toClose;
2009 foreach (IEditor *editor, editorManager->openedEditors()) {
2010 if (editor->property(Constants::OPENED_BY_DEBUGGER).toBool()) {
2011 // Close disassembly views. Close other opened files
2012 // if they are not modified and not current editor.
2013 if (editor->property(Constants::OPENED_WITH_DISASSEMBLY).toBool()
2014 || (!editor->file()->isModified()
2015 && editor != editorManager->currentEditor())) {
2016 toClose.append(editor);
2018 editor->setProperty(Constants::OPENED_BY_DEBUGGER, false);
2022 editorManager->closeEditors(toClose);
2025 void DebuggerPluginPrivate::setBusyCursor(bool busy)
2027 //STATE_DEBUG("BUSY FROM: " << m_busy << " TO: " << busy);
2031 QCursor cursor(busy ? Qt::BusyCursor : Qt::ArrowCursor);
2032 m_breakWindow->setCursor(cursor);
2033 //m_consoleWindow->setCursor(cursor);
2034 m_localsWindow->setCursor(cursor);
2035 m_modulesWindow->setCursor(cursor);
2036 m_logWindow->setCursor(cursor);
2037 m_registerWindow->setCursor(cursor);
2038 m_returnWindow->setCursor(cursor);
2039 m_sourceFilesWindow->setCursor(cursor);
2040 m_stackWindow->setCursor(cursor);
2041 m_threadsWindow->setCursor(cursor);
2042 m_watchersWindow->setCursor(cursor);
2043 m_snapshotWindow->setCursor(cursor);
2044 m_scriptConsoleWindow->setCursor(cursor);
2047 void DebuggerPluginPrivate::setInitialState()
2049 m_watchersWindow->setVisible(false);
2050 m_returnWindow->setVisible(false);
2051 setBusyCursor(false);
2052 m_reverseDirectionAction->setChecked(false);
2053 m_reverseDirectionAction->setEnabled(false);
2054 m_toolTipManager->closeAllToolTips();
2056 m_startExternalAction->setEnabled(true);
2057 m_attachExternalAction->setEnabled(true);
2058 m_attachToQmlPortAction->setEnabled(true);
2059 m_attachCoreAction->setEnabled(true);
2060 m_startRemoteAction->setEnabled(true);
2061 m_attachRemoteAction->setEnabled(true);
2062 m_detachAction->setEnabled(false);
2064 m_watchAction1->setEnabled(true);
2065 m_watchAction2->setEnabled(true);
2066 m_breakAction->setEnabled(false);
2067 //m_snapshotAction->setEnabled(false);
2068 action(OperateByInstruction)->setEnabled(false);
2070 m_exitAction->setEnabled(false);
2071 m_resetAction->setEnabled(false);
2073 m_interruptAction->setEnabled(false);
2074 m_continueAction->setEnabled(false);
2076 m_stepAction->setEnabled(true);
2077 m_stepOutAction->setEnabled(false);
2078 m_runToLineAction->setEnabled(false);
2079 m_runToSelectedFunctionAction->setEnabled(true);
2080 m_returnFromFunctionAction->setEnabled(false);
2081 m_jumpToLineAction->setEnabled(false);
2082 m_nextAction->setEnabled(true);
2084 action(AutoDerefPointers)->setEnabled(true);
2085 action(ExpandStack)->setEnabled(false);
2087 m_scriptConsoleWindow->setEnabled(false);
2090 void DebuggerPluginPrivate::updateWatchersWindow()
2092 m_watchersWindow->setVisible(
2093 m_watchersWindow->model()->rowCount(QModelIndex()) > 0);
2094 m_returnWindow->setVisible(
2095 m_returnWindow->model()->rowCount(QModelIndex()) > 0);
2098 void DebuggerPluginPrivate::updateState(DebuggerEngine *engine)
2100 QTC_ASSERT(engine, return);
2101 QTC_ASSERT(m_watchersWindow->model(), return);
2102 QTC_ASSERT(m_returnWindow->model(), return);
2103 QTC_ASSERT(!engine->isSlaveEngine(), return);
2105 m_threadBox->setCurrentIndex(engine->threadsHandler()->currentThread());
2107 updateWatchersWindow();
2109 const DebuggerState state = engine->state();
2110 //showMessage(QString("PLUGIN SET STATE: ")
2111 // + DebuggerEngine::stateName(state), LogStatus);
2112 //qDebug() << "PLUGIN SET STATE: " << state;
2114 static DebuggerState previousState = DebuggerNotReady;
2115 if (state == previousState)
2118 bool actionsEnabled = DebuggerEngine::debuggerActionsEnabled(state);
2120 if (state == DebuggerNotReady) {
2121 QTC_ASSERT(false, /* We use the Core's m_debugAction here */);
2122 // F5 starts debugging. It is "startable".
2123 m_interruptAction->setEnabled(false);
2124 m_continueAction->setEnabled(false);
2125 m_exitAction->setEnabled(false);
2126 m_startAction->setEnabled(true);
2127 m_visibleStartAction->setAction(m_startAction);
2128 m_hiddenStopAction->setAction(m_undisturbableAction);
2129 } else if (state == InferiorStopOk) {
2130 // F5 continues, Shift-F5 kills. It is "continuable".
2131 m_interruptAction->setEnabled(false);
2132 m_continueAction->setEnabled(true);
2133 m_exitAction->setEnabled(true);
2134 m_startAction->setEnabled(false);
2135 m_visibleStartAction->setAction(m_continueAction);
2136 m_hiddenStopAction->setAction(m_exitAction);
2137 } else if (state == InferiorRunOk) {
2138 // Shift-F5 interrupts. It is also "interruptible".
2139 m_interruptAction->setEnabled(true);
2140 m_continueAction->setEnabled(false);
2141 m_exitAction->setEnabled(true);
2142 m_startAction->setEnabled(false);
2143 m_visibleStartAction->setAction(m_interruptAction);
2144 m_hiddenStopAction->setAction(m_interruptAction);
2145 } else if (state == DebuggerFinished) {
2146 // We don't want to do anything anymore.
2147 m_interruptAction->setEnabled(false);
2148 m_continueAction->setEnabled(false);
2149 m_exitAction->setEnabled(false);
2150 m_startAction->setEnabled(true);
2151 m_visibleStartAction->setAction(m_startAction);
2152 m_hiddenStopAction->setAction(m_undisturbableAction);
2153 m_codeModelSnapshot = CPlusPlus::Snapshot();
2154 setBusyCursor(false);
2156 } else if (state == InferiorUnrunnable) {
2157 // We don't want to do anything anymore.
2158 m_interruptAction->setEnabled(false);
2159 m_continueAction->setEnabled(false);
2160 m_exitAction->setEnabled(true);
2161 m_startAction->setEnabled(false);
2162 m_visibleStartAction->setAction(m_startAction);
2163 m_hiddenStopAction->setAction(m_undisturbableAction);
2165 // Everything else is "undisturbable".
2166 m_interruptAction->setEnabled(false);
2167 m_continueAction->setEnabled(false);
2168 m_exitAction->setEnabled(false);
2169 m_startAction->setEnabled(false);
2170 m_visibleStartAction->setAction(m_undisturbableAction);
2171 m_hiddenStopAction->setAction(m_undisturbableAction);
2174 m_startExternalAction->setEnabled(true);
2175 m_attachToQmlPortAction->setEnabled(true);
2176 m_attachExternalAction->setEnabled(true);
2177 m_attachCoreAction->setEnabled(true);
2178 m_startRemoteAction->setEnabled(true);
2179 m_attachRemoteAction->setEnabled(true);
2181 const bool isCore = engine->startParameters().startMode == AttachCore;
2182 const bool stopped = state == InferiorStopOk;
2183 const bool detachable = stopped && !isCore;
2184 m_detachAction->setEnabled(detachable);
2187 QApplication::alert(mainWindow(), 3000);
2189 const uint caps = engine->debuggerCapabilities();
2190 const bool canReverse = (caps & ReverseSteppingCapability)
2191 && boolSetting(EnableReverseDebugging);
2192 m_reverseDirectionAction->setEnabled(canReverse);
2194 m_watchAction1->setEnabled(true);
2195 m_watchAction2->setEnabled(true);
2196 m_breakAction->setEnabled(true);
2198 const bool canOperateByInstruction = (caps & OperateByInstructionCapability)
2199 && (stopped || isCore);
2200 action(OperateByInstruction)->setEnabled(canOperateByInstruction);
2202 m_resetAction->setEnabled(state != DebuggerNotReady
2203 && state != DebuggerFinished);
2205 m_stepAction->setEnabled(stopped || state == DebuggerNotReady);
2206 m_nextAction->setEnabled(stopped || state == DebuggerNotReady);
2207 m_stepAction->setToolTip(QString());
2208 m_nextAction->setToolTip(QString());
2210 m_stepOutAction->setEnabled(stopped);
2211 m_runToLineAction->setEnabled(stopped && (caps & RunToLineCapability));
2212 m_runToSelectedFunctionAction->setEnabled(stopped);
2213 m_returnFromFunctionAction->
2214 setEnabled(stopped && (caps & ReturnFromFunctionCapability));
2216 const bool canJump = stopped && (caps & JumpToLineCapability);
2217 m_jumpToLineAction->setEnabled(canJump);
2219 const bool canDeref = actionsEnabled && (caps & AutoDerefPointersCapability);
2220 action(AutoDerefPointers)->setEnabled(canDeref);
2221 action(AutoDerefPointers)->setEnabled(true);
2222 action(ExpandStack)->setEnabled(actionsEnabled);
2224 const bool notbusy = state == InferiorStopOk
2225 || state == DebuggerNotReady
2226 || state == DebuggerFinished
2227 || state == InferiorUnrunnable;
2228 setBusyCursor(!notbusy);
2230 //Console should be enabled only for QML
2231 QmlEngine *qmlEngine = qobject_cast<QmlEngine *>(engine);
2232 QmlCppEngine *qmlCppEngine = qobject_cast<QmlCppEngine *>(engine);
2234 qmlEngine = qobject_cast<QmlEngine *>(qmlCppEngine->qmlEngine());
2237 m_scriptConsoleWindow->setEnabled(stopped);
2242 void DebuggerPluginPrivate::updateDebugActions()
2244 ProjectExplorerPlugin *pe = ProjectExplorerPlugin::instance();
2245 Project *project = pe->startupProject();
2246 const QString debugMode = _(Constants::DEBUGMODE);
2247 const bool canRun = pe->canRun(project, debugMode);
2248 m_startAction->setEnabled(canRun);
2249 m_startAction->setToolTip(canRun ? QString() : pe->cannotRunReason(project, debugMode));
2251 // Step into/next: Start and break at 'main' unless a debugger is running.
2252 if (m_snapshotHandler->currentIndex() < 0) {
2253 const QString debugMode2 = _(Constants::DEBUGMODE2);
2254 const bool canRunAndBreakMain = pe->canRun(project, debugMode2);
2255 m_stepAction->setEnabled(canRunAndBreakMain);
2256 m_nextAction->setEnabled(canRunAndBreakMain);
2258 if (canRunAndBreakMain) {
2259 QTC_ASSERT(project, return ; );
2260 toolTip = tr("Start '%1' and break at function 'main()'")
2261 .arg(project->displayName());
2263 // Do not display long tooltip saying 'debugMode2 is not supported
2264 // for project' for projects to which 'break at main' is not applicable.
2266 toolTip = pe->cannotRunReason(project, debugMode2);
2268 m_stepAction->setToolTip(toolTip);
2269 m_nextAction->setToolTip(toolTip);
2273 void DebuggerPluginPrivate::onCoreAboutToOpen()
2275 m_mainWindow->onModeChanged(ModeManager::instance()->currentMode());
2278 void DebuggerPluginPrivate::onModeChanged(IMode *mode)
2280 // FIXME: This one gets always called, even if switching between modes
2281 // different then the debugger mode. E.g. Welcome and Help mode and
2282 // also on shutdown.
2284 m_mainWindow->onModeChanged(mode);
2286 if (mode->id() != Constants::MODE_DEBUG) {
2287 m_toolTipManager->leavingDebugMode();
2291 EditorManager *editorManager = EditorManager::instance();
2292 if (editorManager->currentEditor())
2293 editorManager->currentEditor()->widget()->setFocus();
2294 m_toolTipManager->debugModeEntered();
2297 void DebuggerPluginPrivate::showSettingsDialog()
2299 ICore::instance()->showOptionsDialog(
2300 _(DEBUGGER_SETTINGS_CATEGORY),
2301 _(DEBUGGER_COMMON_SETTINGS_ID));
2304 void DebuggerPluginPrivate::dumpLog()
2306 QString fileName = QFileDialog::getSaveFileName(mainWindow(),
2307 tr("Save Debugger Log"), QDir::tempPath());
2308 if (fileName.isEmpty())
2310 Utils::FileSaver saver(fileName);
2311 if (!saver.hasError()) {
2312 QTextStream ts(saver.file());
2313 ts << m_logWindow->inputContents();
2314 ts << "\n\n=======================================\n\n";
2315 ts << m_logWindow->combinedContents();
2316 saver.setResult(&ts);
2318 saver.finalize(mainWindow());
2321 /*! Activates the previous mode when the current mode is the debug mode. */
2322 void DebuggerPluginPrivate::activatePreviousMode()
2324 ModeManager *modeManager = ModeManager::instance();
2325 if (modeManager->currentMode() == modeManager->mode(MODE_DEBUG)
2326 && !m_previousMode.isEmpty()) {
2327 modeManager->activateMode(m_previousMode);
2328 m_previousMode.clear();
2332 void DebuggerPluginPrivate::activateDebugMode()
2334 m_reverseDirectionAction->setChecked(false);
2335 m_reverseDirectionAction->setEnabled(false);
2336 ModeManager *modeManager = ModeManager::instance();
2337 m_previousMode = modeManager->currentMode()->id();
2338 modeManager->activateMode(_(MODE_DEBUG));
2341 void DebuggerPluginPrivate::sessionLoaded()
2343 m_breakHandler->loadSessionData();
2344 dummyEngine()->watchHandler()->loadSessionData();
2345 m_toolTipManager->loadSessionData();
2348 void DebuggerPluginPrivate::aboutToUnloadSession()
2350 m_breakHandler->removeSessionData();
2351 m_toolTipManager->sessionAboutToChange();
2352 // Stop debugging the active project when switching sessions.
2353 // Note that at startup, session switches may occur, which interfere
2354 // with command-line debugging startup.
2355 // FIXME ABC: Still wanted? Iterate?
2356 //if (d->m_engine && state() != DebuggerNotReady
2357 // && engine()->sp().startMode == StartInternal)
2358 // d->m_engine->shutdown();
2361 void DebuggerPluginPrivate::aboutToSaveSession()
2363 dummyEngine()->watchHandler()->saveSessionData();
2364 m_toolTipManager->saveSessionData();
2365 m_breakHandler->saveSessionData();
2368 void DebuggerPluginPrivate::executeDebuggerCommand(const QString &command)
2370 if (currentEngine()->acceptsDebuggerCommands())
2371 currentEngine()->executeDebuggerCommand(command);
2373 showStatusMessage(tr("User commands are not accepted in the current state."));
2376 void DebuggerPluginPrivate::showStatusMessage(const QString &msg0, int timeout)
2378 showMessage(msg0, LogStatus);
2380 msg.remove(QLatin1Char('\n'));
2381 m_statusLabel->showStatusMessage(msg, timeout);
2384 void DebuggerPluginPrivate::scriptExpressionEntered(const QString &expression)
2386 currentEngine()->executeDebuggerCommand(expression);
2389 void DebuggerPluginPrivate::openMemoryEditor()
2391 AddressDialog dialog;
2392 if (dialog.exec() == QDialog::Accepted)
2393 currentEngine()->openMemoryView(dialog.address(), 0, QList<MemoryMarkup>(), QPoint());
2396 void DebuggerPluginPrivate::coreShutdown()
2398 m_shuttingDown = true;
2401 const CPlusPlus::Snapshot &DebuggerPluginPrivate::cppCodeModelSnapshot() const
2403 if (m_codeModelSnapshot.isEmpty() && action(UseCodeModel)->isChecked())
2404 m_codeModelSnapshot = CPlusPlus::CppModelManagerInterface::instance()->snapshot();
2405 return m_codeModelSnapshot;
2408 void DebuggerPluginPrivate::setSessionValue(const QString &name, const QVariant &value)
2410 QTC_ASSERT(sessionManager(), return);
2411 sessionManager()->setValue(name, value);
2412 //qDebug() << "SET SESSION VALUE: " << name;
2415 QVariant DebuggerPluginPrivate::sessionValue(const QString &name)
2417 QTC_ASSERT(sessionManager(), return QVariant());
2418 //qDebug() << "GET SESSION VALUE: " << name;
2419 return sessionManager()->value(name);
2422 void DebuggerPluginPrivate::openTextEditor(const QString &titlePattern0,
2423 const QString &contents)
2427 QString titlePattern = titlePattern0;
2428 EditorManager *editorManager = EditorManager::instance();
2429 QTC_ASSERT(editorManager, return);
2430 IEditor *editor = editorManager->openEditorWithContents(
2431 CC::K_DEFAULT_TEXT_EDITOR_ID, &titlePattern, contents);
2432 QTC_ASSERT(editor, return);
2433 editorManager->activateEditor(editor, EditorManager::IgnoreNavigationHistory);
2437 void DebuggerPluginPrivate::clearCppCodeModelSnapshot()
2439 m_codeModelSnapshot = CPlusPlus::Snapshot();
2442 void DebuggerPluginPrivate::showMessage(const QString &msg, int channel, int timeout)
2444 //qDebug() << "PLUGIN OUTPUT: " << channel << msg;
2445 //ConsoleWindow *cw = m_consoleWindow;
2446 QTC_ASSERT(m_logWindow, return);
2449 // This will append to m_logWindow's output pane, too.
2450 showStatusMessage(msg, timeout);
2453 m_logWindow->showInput(LogMisc, msg);
2454 m_logWindow->showOutput(LogMisc, msg);
2457 m_logWindow->showInput(LogInput, msg);
2458 m_logWindow->showOutput(LogInput, msg);
2460 case ScriptConsoleOutput:
2461 m_scriptConsoleWindow->appendResult(msg);
2464 m_logWindow->showOutput(channel, msg);
2465 QAction *action = m_mainWindow->dockWidget(_(DOCKWIDGET_OUTPUT))
2466 ->toggleViewAction();
2467 if (!action->isChecked())
2472 m_logWindow->showOutput(channel, msg);
2477 void DebuggerPluginPrivate::showQtDumperLibraryWarning(const QString &details)
2479 QMessageBox dialog(mainWindow());
2480 QPushButton *qtPref = dialog.addButton(tr("Open Qt4 Options"),
2481 QMessageBox::ActionRole);
2482 QPushButton *helperOff = dialog.addButton(tr("Turn off Helper Usage"),
2483 QMessageBox::ActionRole);
2484 QPushButton *justContinue = dialog.addButton(tr("Continue Anyway"),
2485 QMessageBox::AcceptRole);
2486 dialog.setDefaultButton(justContinue);
2487 dialog.setWindowTitle(tr("Debugging Helper Missing"));
2488 dialog.setText(tr("The debugger could not load the debugging helper library."));
2489 dialog.setInformativeText(tr(
2490 "The debugging helper is used to nicely format the values of some Qt "
2491 "and Standard Library data types. "
2492 "It must be compiled for each used Qt version separately. "
2493 "On the Qt4 options page, select a Qt installation "
2494 "and click Rebuild."));
2495 if (!details.isEmpty())
2496 dialog.setDetailedText(details);
2498 if (dialog.clickedButton() == qtPref) {
2499 ICore::instance()->showOptionsDialog(
2500 _(ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_CATEGORY),
2501 _(QtSupport::Constants::QTVERSION_SETTINGS_PAGE_ID));
2502 } else if (dialog.clickedButton() == helperOff) {
2503 action(UseDebuggingHelpers)->setValue(qVariantFromValue(false), false);
2507 void DebuggerPluginPrivate::createNewDock(QWidget *widget)
2509 QDockWidget *dockWidget =
2510 m_mainWindow->createDockWidget(CppLanguage, widget);
2511 dockWidget->setWindowTitle(widget->windowTitle());
2512 dockWidget->setFeatures(QDockWidget::DockWidgetClosable);
2516 static QString formatStartParameters(DebuggerStartParameters &sp)
2519 QTextStream str(&rc);
2520 str << "Start parameters: '" << sp.displayName << "' mode: " << sp.startMode
2521 << "\nABI: " << sp.toolChainAbi.toString() << '\n';
2522 if (!sp.executable.isEmpty()) {
2523 str << "Executable: " << QDir::toNativeSeparators(sp.executable)
2524 << ' ' << sp.processArgs;
2526 str << " [terminal]";
2528 if (!sp.workingDirectory.isEmpty())
2529 str << "Directory: " << QDir::toNativeSeparators(sp.workingDirectory)
2531 if (sp.executableUid) {
2533 str.setIntegerBase(16);
2534 str << sp.executableUid << '\n';
2535 str.setIntegerBase(10);
2538 if (!sp.debuggerCommand.isEmpty())
2539 str << "Debugger: " << QDir::toNativeSeparators(sp.debuggerCommand) << '\n';
2540 if (!sp.coreFile.isEmpty())
2541 str << "Core: " << QDir::toNativeSeparators(sp.coreFile) << '\n';
2542 if (sp.attachPID > 0)
2543 str << "PID: " << sp.attachPID << ' ' << sp.crashParameter << '\n';
2544 if (!sp.projectSourceDirectory.isEmpty()) {
2545 str << "Project: " << QDir::toNativeSeparators(sp.projectSourceDirectory);
2546 if (!sp.projectBuildDirectory.isEmpty())
2547 str << " (built: " << QDir::toNativeSeparators(sp.projectBuildDirectory)
2551 if (!sp.qtInstallPath.isEmpty())
2552 str << "Qt: " << QDir::toNativeSeparators(sp.qtInstallPath) << '\n';
2553 if (!sp.qmlServerAddress.isEmpty())
2554 str << "QML server: " << sp.qmlServerAddress << ':'
2555 << sp.qmlServerPort << '\n';
2556 if (!sp.remoteChannel.isEmpty()) {
2557 str << "Remote: " << sp.remoteChannel << ", "
2558 << sp.remoteArchitecture << '\n';
2559 if (!sp.remoteDumperLib.isEmpty())
2560 str << "Remote dumpers: " << sp.remoteDumperLib << '\n';
2561 if (!sp.remoteSourcesDir.isEmpty())
2562 str << "Remote sources: " << sp.remoteSourcesDir << '\n';
2563 if (!sp.remoteMountPoint.isEmpty())
2564 str << "Remote mount point: " << sp.remoteMountPoint
2565 << " Local: " << sp.localMountDir << '\n';
2567 if (!sp.gnuTarget.isEmpty())
2568 str << "Gnu target: " << sp.gnuTarget << '\n';
2569 str << "Sysroot: " << sp.sysroot << '\n';
2570 str << "Debug Source Loaction: " << sp.debugSourceLocation.join(":") << '\n';
2571 str << "Symbol file: " << sp.symbolFileName << '\n';
2572 if (sp.useServerStartScript)
2573 str << "Using server start script: " << sp.serverStartScript;
2574 str << "Dumper libraries: " << QDir::toNativeSeparators(sp.dumperLibrary);
2575 foreach (const QString &dl, sp.dumperLibraryLocations)
2576 str << ' ' << QDir::toNativeSeparators(dl);
2581 void DebuggerPluginPrivate::runControlStarted(DebuggerEngine *engine)
2583 activateDebugMode();
2584 const QString message = tr("Starting debugger '%1' for ABI '%2'...")
2585 .arg(engine->objectName())
2586 .arg(engine->startParameters().toolChainAbi.toString());
2587 showMessage(message, StatusBar);
2588 showMessage(formatStartParameters(engine->startParameters()), LogDebug);
2589 showMessage(m_debuggerSettings->dump(), LogDebug);
2590 m_snapshotHandler->appendSnapshot(engine);
2591 connectEngine(engine);
2594 void DebuggerPluginPrivate::runControlFinished(DebuggerEngine *engine)
2596 showStatusMessage(tr("Debugger finished."));
2597 m_snapshotHandler->removeSnapshot(engine);
2598 if (m_snapshotHandler->size() == 0) {
2599 // Last engine quits.
2601 if (boolSetting(SwitchModeOnExit))
2602 activatePreviousMode();
2604 // Connect to some existing engine.
2605 m_snapshotHandler->activateSnapshot(0);
2607 action(OperateByInstruction)->setValue(QVariant(false));
2610 void DebuggerPluginPrivate::remoteCommand(const QStringList &options,
2611 const QStringList &)
2613 if (options.isEmpty())
2616 unsigned enabledEngines = 0;
2617 QString errorMessage;
2619 if (!parseArguments(options, &enabledEngines, &errorMessage)) {
2620 qWarning("%s", qPrintable(errorMessage));
2626 QString DebuggerPluginPrivate::debuggerForAbi(const Abi &abi, DebuggerEngineType et) const
2629 QList<Abi> searchAbis;
2630 searchAbis.push_back(abi);
2631 // Pick the right tool chain in case cdb/gdb were started with other tool chains.
2632 // Also, lldb should be preferred over gdb.
2633 if (abi.os() == ProjectExplorer::Abi::WindowsOS) {
2637 searchAbis.push_back(Abi(abi.architecture(), abi.os(),
2638 Abi::WindowsMsvc2010Flavor, abi.binaryFormat(), abi.wordWidth()));
2639 searchAbis.push_back(Abi(abi.architecture(), abi.os(),
2640 Abi::WindowsMsvc2008Flavor, abi.binaryFormat(), abi.wordWidth()));
2641 searchAbis.push_back(Abi(abi.architecture(), abi.os(),
2642 Abi::WindowsMsvc2005Flavor, abi.binaryFormat(), abi.wordWidth()));
2646 searchAbis.push_back(Abi(abi.architecture(), abi.os(),
2647 Abi::WindowsMSysFlavor, abi.binaryFormat(), abi.wordWidth()));
2654 qDebug() << "debuggerForAbi" << abi.toString() << searchAbis.size()
2655 << searchAbis.front().toString() << et;
2657 foreach (const Abi &searchAbi, searchAbis) {
2658 const QList<ToolChain *> toolchains =
2659 ToolChainManager::instance()->findToolChains(searchAbi);
2660 // Find manually configured ones first
2661 for (int i = toolchains.size() - 1; i >= 0; i--) {
2662 const QString debugger = toolchains.at(i)->debuggerCommand();
2664 qDebug() << i << toolchains.at(i)->displayName() << debugger;
2665 if (!debugger.isEmpty())
2672 DebuggerLanguages DebuggerPluginPrivate::activeLanguages() const
2674 QTC_ASSERT(m_mainWindow, return AnyLanguage);
2675 return m_mainWindow->activeDebugLanguages();
2678 bool DebuggerPluginPrivate::isReverseDebugging() const
2680 return m_reverseDirectionAction->isChecked();
2683 QMessageBox *showMessageBox(int icon, const QString &title,
2684 const QString &text, int buttons)
2686 QMessageBox *mb = new QMessageBox(QMessageBox::Icon(icon),
2687 title, text, QMessageBox::StandardButtons(buttons),
2688 debuggerCore()->mainWindow());
2689 mb->setAttribute(Qt::WA_DeleteOnClose);
2694 void DebuggerPluginPrivate::extensionsInitialized()
2696 ICore *core = ICore::instance();
2697 QTC_ASSERT(core, return);
2698 m_coreSettings = core->settings();
2700 m_debuggerSettings = new DebuggerSettings(m_coreSettings);
2701 m_debuggerSettings->readSettings();
2703 connect(core, SIGNAL(coreAboutToClose()), this, SLOT(coreShutdown()));
2705 Core::ActionManager *am = core->actionManager();
2706 QTC_ASSERT(am, return);
2708 m_plugin->addObject(this);
2710 const Context globalcontext(CC::C_GLOBAL);
2711 const Context cppDebuggercontext(C_CPPDEBUGGER);
2712 const Context qmlDebuggerContext(C_QMLDEBUGGER);
2713 const Context cppeditorcontext(CppEditor::Constants::C_CPPEDITOR);
2715 m_startIcon = QIcon(_(":/debugger/images/debugger_start_small.png"));
2716 m_startIcon.addFile(__(":/debugger/images/debugger_start.png"));
2717 m_exitIcon = QIcon(_(":/debugger/images/debugger_stop_small.png"));
2718 m_exitIcon.addFile(__(":/debugger/images/debugger_stop.png"));
2719 m_continueIcon = QIcon(__(":/debugger/images/debugger_continue_small.png"));
2720 m_continueIcon.addFile(__(":/debugger/images/debugger_continue.png"));
2721 m_interruptIcon = QIcon(_(":/debugger/images/debugger_interrupt_small.png"));
2722 m_interruptIcon.addFile(__(":/debugger/images/debugger_interrupt.png"));
2723 m_locationMarkIcon = QIcon(_(":/debugger/images/location_16.png"));
2727 m_statusLabel = new Utils::StatusLabel;
2729 m_breakHandler = new BreakHandler;
2730 m_breakWindow = new BreakWindow;
2731 m_breakWindow->setObjectName(DOCKWIDGET_BREAK);
2732 m_breakWindow->setModel(m_breakHandler->model());
2734 //m_consoleWindow = new ConsoleWindow;
2735 //m_consoleWindow->setObjectName(QLatin1String("CppDebugConsole"));
2736 m_modulesWindow = new ModulesWindow;
2737 m_modulesWindow->setObjectName(DOCKWIDGET_MODULES);
2738 m_logWindow = new LogWindow;
2739 m_logWindow->setObjectName(DOCKWIDGET_OUTPUT);
2740 m_registerWindow = new RegisterWindow;
2741 m_registerWindow->setObjectName(DOCKWIDGET_REGISTER);
2742 m_stackWindow = new StackWindow;
2743 m_stackWindow->setObjectName(DOCKWIDGET_STACK);
2744 m_sourceFilesWindow = new SourceFilesWindow;
2745 m_sourceFilesWindow->setObjectName(DOCKWIDGET_SOURCE_FILES);
2746 m_threadsWindow = new ThreadsWindow;
2747 m_threadsWindow->setObjectName(DOCKWIDGET_THREADS);
2748 m_returnWindow = new WatchWindow(WatchWindow::ReturnType);
2749 m_returnWindow->setObjectName(QLatin1String("CppDebugReturn"));
2750 m_localsWindow = new WatchWindow(WatchWindow::LocalsType);
2751 m_localsWindow->setObjectName(QLatin1String("CppDebugLocals"));
2752 m_watchersWindow = new WatchWindow(WatchWindow::WatchersType);
2753 m_watchersWindow->setObjectName(QLatin1String("CppDebugWatchers"));
2754 m_scriptConsoleWindow = new ScriptConsole;
2755 m_scriptConsoleWindow->setWindowTitle(tr("QML Script Console"));
2756 m_scriptConsoleWindow->setObjectName(DOCKWIDGET_QML_SCRIPTCONSOLE);
2757 connect(m_scriptConsoleWindow, SIGNAL(expressionEntered(QString)),
2758 SLOT(scriptExpressionEntered(QString)));
2761 m_snapshotHandler = new SnapshotHandler;
2762 m_snapshotWindow = new SnapshotWindow(m_snapshotHandler);
2763 m_snapshotWindow->setObjectName(DOCKWIDGET_SNAPSHOTS);
2764 m_snapshotWindow->setModel(m_snapshotHandler->model());
2767 connect(m_localsWindow->header(), SIGNAL(sectionResized(int,int,int)),
2768 SLOT(updateWatchersHeader(int,int,int)), Qt::QueuedConnection);
2772 act = m_continueAction = new QAction(tr("Continue"), this);
2773 act->setIcon(m_continueIcon);
2774 connect(act, SIGNAL(triggered()), SLOT(handleExecContinue()));
2776 act = m_exitAction = new QAction(tr("Exit Debugger"), this);
2777 act->setIcon(m_exitIcon);
2778 connect(act, SIGNAL(triggered()), SLOT(handleExecExit()));
2780 act = m_interruptAction = new QAction(tr("Interrupt"), this);
2781 act->setIcon(m_interruptIcon);
2782 connect(act, SIGNAL(triggered()), SLOT(handleExecInterrupt()));
2784 // A "disabled pause" seems to be a good choice.
2785 act = m_undisturbableAction = new QAction(tr("Debugger is Busy"), this);
2786 act->setIcon(m_interruptIcon);
2787 act->setEnabled(false);
2789 act = m_resetAction = new QAction(tr("Abort Debugging"), this);
2790 act->setToolTip(tr("Aborts debugging and "
2791 "resets the debugger to the initial state."));
2792 connect(act, SIGNAL(triggered()), SLOT(handleExecReset()));
2794 act = m_nextAction = new QAction(tr("Step Over"), this);
2795 act->setIcon(QIcon(__(":/debugger/images/debugger_stepover_small.png")));
2796 connect(act, SIGNAL(triggered()), SLOT(handleExecNext()));
2798 act = m_stepAction = new QAction(tr("Step Into"), this);
2799 act->setIcon(QIcon(__(":/debugger/images/debugger_stepinto_small.png")));
2800 connect(act, SIGNAL(triggered()), SLOT(handleExecStep()));
2802 act = m_stepOutAction = new QAction(tr("Step Out"), this);
2803 act->setIcon(QIcon(__(":/debugger/images/debugger_stepout_small.png")));
2804 connect(act, SIGNAL(triggered()), SLOT(handleExecStepOut()));
2806 act = m_runToLineAction = new QAction(tr("Run to Line"), this);
2807 connect(act, SIGNAL(triggered()), SLOT(handleExecRunToLine()));
2809 act = m_runToSelectedFunctionAction =
2810 new QAction(tr("Run to Selected Function"), this);
2811 connect(act, SIGNAL(triggered()), SLOT(handleExecRunToSelectedFunction()));
2813 act = m_returnFromFunctionAction =
2814 new QAction(tr("Immediately Return From Inner Function"), this);
2815 connect(act, SIGNAL(triggered()), SLOT(handleExecReturn()));
2817 act = m_jumpToLineAction = new QAction(tr("Jump to Line"), this);
2818 connect(act, SIGNAL(triggered()), SLOT(handleExecJumpToLine()));
2820 act = m_breakAction = new QAction(tr("Toggle Breakpoint"), this);
2822 act = m_watchAction1 = new QAction(tr("Add to Watch Window"), this);
2823 connect(act, SIGNAL(triggered()), SLOT(handleAddToWatchWindow()));
2825 act = m_watchAction2 = new QAction(tr("Add to Watch Window"), this);
2826 connect(act, SIGNAL(triggered()), SLOT(handleAddToWatchWindow()));
2828 //m_snapshotAction = new QAction(tr("Create Snapshot"), this);
2829 //m_snapshotAction->setProperty(Role, RequestCreateSnapshotRole);
2830 //m_snapshotAction->setIcon(
2831 // QIcon(__(":/debugger/images/debugger_snapshot_small.png")));
2833 act = m_reverseDirectionAction =
2834 new QAction(tr("Reverse Direction"), this);
2835 act->setCheckable(true);
2836 act->setChecked(false);
2837 act->setCheckable(false);
2838 act->setIcon(QIcon(__(":/debugger/images/debugger_reversemode_16.png")));
2839 act->setIconVisibleInMenu(false);
2841 act = m_frameDownAction = new QAction(tr("Move to Called Frame"), this);
2842 connect(act, SIGNAL(triggered()), SLOT(handleFrameDown()));
2844 act = m_frameUpAction = new QAction(tr("Move to Calling Frame"), this);
2845 connect(act, SIGNAL(triggered()), SLOT(handleFrameUp()));
2847 connect(action(OperateByInstruction), SIGNAL(triggered(bool)),
2848 SLOT(handleOperateByInstructionTriggered(bool)));
2850 ActionContainer *debugMenu =
2851 am->actionContainer(ProjectExplorer::Constants::M_DEBUG);
2854 QDockWidget *dock = 0;
2855 dock = m_mainWindow->createDockWidget(CppLanguage, m_modulesWindow);
2856 connect(dock->toggleViewAction(), SIGNAL(toggled(bool)),
2857 SLOT(modulesDockToggled(bool)), Qt::QueuedConnection);
2859 dock = m_mainWindow->createDockWidget(CppLanguage, m_registerWindow);
2860 connect(dock->toggleViewAction(), SIGNAL(toggled(bool)),
2861 SLOT(registerDockToggled(bool)), Qt::QueuedConnection);
2863 dock = m_mainWindow->createDockWidget(CppLanguage, m_sourceFilesWindow);
2864 connect(dock->toggleViewAction(), SIGNAL(toggled(bool)),
2865 SLOT(sourceFilesDockToggled(bool)), Qt::QueuedConnection);
2867 dock = m_mainWindow->createDockWidget(AnyLanguage, m_logWindow);
2868 dock->setProperty(DOCKWIDGET_DEFAULT_AREA, Qt::TopDockWidgetArea);
2870 m_mainWindow->createDockWidget(CppLanguage, m_breakWindow);
2871 //m_mainWindow->createDockWidget(CppLanguage, m_consoleWindow);
2872 m_mainWindow->createDockWidget(CppLanguage, m_snapshotWindow);
2873 m_mainWindow->createDockWidget(CppLanguage, m_stackWindow);
2874 m_mainWindow->createDockWidget(CppLanguage, m_threadsWindow);
2875 m_mainWindow->createDockWidget(QmlLanguage, m_scriptConsoleWindow);
2877 QSplitter *localsAndWatchers = new Core::MiniSplitter(Qt::Vertical);
2878 localsAndWatchers->setObjectName(DOCKWIDGET_WATCHERS);
2879 localsAndWatchers->setWindowTitle(m_localsWindow->windowTitle());
2880 localsAndWatchers->addWidget(m_localsWindow);
2881 localsAndWatchers->addWidget(m_returnWindow);
2882 localsAndWatchers->addWidget(m_watchersWindow);
2883 localsAndWatchers->setStretchFactor(0, 3);
2884 localsAndWatchers->setStretchFactor(1, 1);
2885 localsAndWatchers->setStretchFactor(2, 1);
2887 dock = m_mainWindow->createDockWidget(CppLanguage, localsAndWatchers);
2888 dock->setProperty(DOCKWIDGET_DEFAULT_AREA, Qt::RightDockWidgetArea);
2890 m_commonOptionsPage = new CommonOptionsPage(m_globalDebuggerOptions);
2891 m_plugin->addAutoReleasedObject(m_commonOptionsPage);
2893 // Do not fail to load the whole plugin if something goes wrong here.
2894 QString errorMessage;
2895 if (!parseArguments(m_arguments, &m_cmdLineEnabledEngines, &errorMessage)) {
2896 errorMessage = tr("Error evaluating command line arguments: %1")
2898 qWarning("%s\n", qPrintable(errorMessage));
2901 // Register factory of DebuggerRunControl.
2902 m_debuggerRunControlFactory = new DebuggerRunControlFactory
2903 (m_plugin, DebuggerEngineType(m_cmdLineEnabledEngines));
2904 m_plugin->addAutoReleasedObject(m_debuggerRunControlFactory);
2906 // The main "Start Debugging" action.
2907 act = m_startAction = new QAction(this);
2908 QIcon debuggerIcon(":/projectexplorer/images/debugger_start_small.png");
2909 debuggerIcon.addFile(":/projectexplorer/images/debugger_start.png");
2910 act->setIcon(debuggerIcon);
2911 act->setText(tr("Start Debugging"));
2912 connect(act, SIGNAL(triggered()), this, SLOT(debugProject()));
2914 // Handling of external applications.
2915 act = m_startExternalAction = new QAction(this);
2916 act->setText(tr("Start and Debug External Application..."));
2917 connect(act, SIGNAL(triggered()), SLOT(startExternalApplication()));
2920 act = m_startRemoteLldbAction = new QAction(this);
2921 act->setText(tr("Start and Debug External Application with External Engine..."));
2922 connect(act, SIGNAL(triggered()), SLOT(startRemoteEngine()));
2925 act = m_attachExternalAction = new QAction(this);
2926 act->setText(tr("Attach to Running External Application..."));
2927 connect(act, SIGNAL(triggered()), SLOT(attachExternalApplication()));
2929 act = m_attachCoreAction = new QAction(this);
2930 act->setText(tr("Attach to Core..."));
2931 connect(act, SIGNAL(triggered()), SLOT(attachCore()));
2933 act = m_startRemoteAction = new QAction(this);
2934 act->setText(tr("Start and Debug Remote Application..."));
2935 connect(act, SIGNAL(triggered()), SLOT(startRemoteApplication()));
2937 act = m_attachRemoteAction = new QAction(this);
2938 act->setText(tr("Attach to Remote Debug Server..."));
2939 connect(act, SIGNAL(triggered()), SLOT(attachRemoteApplication()));
2941 act = m_attachToQmlPortAction = new QAction(this);
2942 act->setText(tr("Attach to QML Port..."));
2943 connect(act, SIGNAL(triggered()), SLOT(attachToQmlPort()));
2946 m_startRemoteCdbAction = new QAction(tr("Attach to Remote CDB Session..."), this);
2947 connect(m_startRemoteCdbAction, SIGNAL(triggered()),
2948 SLOT(startRemoteCdbSession()));
2951 act = m_detachAction = new QAction(this);
2952 act->setText(tr("Detach Debugger"));
2953 connect(act, SIGNAL(triggered()), SLOT(handleExecDetach()));
2955 // "Start Debugging" sub-menu
2962 ActionContainer *mstart = am->actionContainer(PE::M_DEBUG_STARTDEBUGGING);
2964 cmd = am->registerAction(m_startAction, Constants::DEBUG, globalcontext);
2965 cmd->setDefaultText(tr("Start Debugging"));
2966 cmd->setDefaultKeySequence(QKeySequence(Constants::DEBUG_KEY));
2967 cmd->setAttribute(Command::CA_UpdateText);
2968 mstart->addAction(cmd, CC::G_DEFAULT_ONE);
2970 m_visibleStartAction = new Utils::ProxyAction(this);
2971 m_visibleStartAction->initialize(m_startAction);
2972 m_visibleStartAction->setAttribute(Utils::ProxyAction::UpdateText);
2973 m_visibleStartAction->setAttribute(Utils::ProxyAction::UpdateIcon);
2974 m_visibleStartAction->setAction(cmd->action());
2976 ModeManager *modeManager = ModeManager::instance();
2977 modeManager->addAction(m_visibleStartAction, Constants::P_ACTION_DEBUG);
2979 cmd = am->registerAction(m_startExternalAction,
2980 "Debugger.StartExternal", globalcontext);
2981 cmd->setAttribute(Command::CA_Hide);
2982 mstart->addAction(cmd, Constants::G_START_CPP);
2984 cmd = am->registerAction(m_attachExternalAction,
2985 "Debugger.AttachExternal", globalcontext);
2986 cmd->setAttribute(Command::CA_Hide);
2987 mstart->addAction(cmd, Constants::G_START_CPP);
2989 cmd = am->registerAction(m_attachCoreAction,
2990 "Debugger.AttachCore", globalcontext);
2992 cmd->setAttribute(Command::CA_Hide);
2993 mstart->addAction(cmd, Constants::G_START_CPP);
2995 cmd = am->registerAction(m_startRemoteAction,
2996 "Debugger.StartRemote", globalcontext);
2997 cmd->setAttribute(Command::CA_Hide);
2998 mstart->addAction(cmd, Constants::G_START_CPP);
3000 cmd = am->registerAction(m_attachRemoteAction,
3001 "Debugger.AttachRemote", globalcontext);
3002 cmd->setAttribute(Command::CA_Hide);
3003 mstart->addAction(cmd, Constants::G_START_CPP);
3007 cmd = am->registerAction(m_startRemoteLldbAction,
3008 "Debugger.RemoteLldb", globalcontext);
3009 cmd->setAttribute(Command::CA_Hide);
3010 mstart->addAction(cmd, Constants::G_START_CPP);
3013 if (m_startRemoteCdbAction) {
3014 cmd = am->registerAction(m_startRemoteCdbAction,
3015 "Debugger.AttachRemoteCdb", globalcontext);
3016 cmd->setAttribute(Command::CA_Hide);
3017 mstart->addAction(cmd, Constants::G_START_CPP);
3020 QAction *sep = new QAction(mstart);
3021 sep->setSeparator(true);
3022 cmd = am->registerAction(sep,
3023 "Debugger.Start.Qml", globalcontext);
3024 mstart->addAction(cmd, Constants::G_START_QML);
3026 cmd = am->registerAction(m_attachToQmlPortAction,
3027 "Debugger.AttachToQmlPort", globalcontext);
3028 cmd->setAttribute(Command::CA_Hide);
3029 mstart->addAction(cmd, Constants::G_START_QML);
3031 cmd = am->registerAction(m_detachAction,
3032 "Debugger.Detach", globalcontext);
3033 cmd->setAttribute(Command::CA_Hide);
3034 debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
3036 cmd = am->registerAction(m_interruptAction,
3037 Constants::INTERRUPT, globalcontext);
3038 cmd->setDefaultText(tr("Interrupt Debugger"));
3039 debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
3041 cmd = am->registerAction(m_continueAction,
3042 Constants::CONTINUE, globalcontext);
3043 cmd->setDefaultKeySequence(QKeySequence(Constants::DEBUG_KEY));
3044 debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
3046 cmd = am->registerAction(m_exitAction,
3047 Constants::STOP, globalcontext);
3048 cmd->setDefaultText(tr("Stop Debugger"));
3049 debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
3051 m_hiddenStopAction = new Utils::ProxyAction(this);
3052 m_hiddenStopAction->initialize(m_exitAction);
3053 m_hiddenStopAction->setAttribute(Utils::ProxyAction::UpdateText);
3054 m_hiddenStopAction->setAttribute(Utils::ProxyAction::UpdateIcon);
3056 cmd = am->registerAction(m_hiddenStopAction,
3057 Constants::HIDDEN_STOP, globalcontext);
3058 cmd->setDefaultKeySequence(QKeySequence(Constants::STOP_KEY));
3060 cmd = am->registerAction(m_resetAction,
3061 Constants::RESET, globalcontext);
3062 //cmd->setDefaultKeySequence(QKeySequence(Constants::RESET_KEY));
3063 cmd->setDefaultText(tr("Reset Debugger"));
3064 debugMenu->addAction(cmd, CC::G_DEFAULT_ONE);
3066 sep = new QAction(this);
3067 sep->setSeparator(true);
3068 cmd = am->registerAction(sep, "Debugger.Sep.Step", globalcontext);
3069 debugMenu->addAction(cmd);
3071 cmd = am->registerAction(m_nextAction,
3072 Constants::NEXT, globalcontext);
3073 cmd->setDefaultKeySequence(QKeySequence(Constants::NEXT_KEY));
3074 cmd->setAttribute(Command::CA_Hide);
3075 cmd->setAttribute(Command::CA_UpdateText);
3076 debugMenu->addAction(cmd);
3078 cmd = am->registerAction(m_stepAction,
3079 Constants::STEP, globalcontext);
3080 cmd->setDefaultKeySequence(QKeySequence(Constants::STEP_KEY));
3081 cmd->setAttribute(Command::CA_Hide);
3082 cmd->setAttribute(Command::CA_UpdateText);
3083 debugMenu->addAction(cmd);
3085 cmd = am->registerAction(m_stepOutAction,
3086 Constants::STEPOUT, cppDebuggercontext);
3087 cmd->setDefaultKeySequence(QKeySequence(Constants::STEPOUT_KEY));
3088 cmd->setAttribute(Command::CA_Hide);
3089 debugMenu->addAction(cmd);
3091 cmd = am->registerAction(m_runToLineAction,
3092 "Debugger.RunToLine", cppDebuggercontext);
3093 cmd->setDefaultKeySequence(QKeySequence(Constants::RUN_TO_LINE_KEY));
3094 cmd->setAttribute(Command::CA_Hide);
3095 debugMenu->addAction(cmd);
3097 cmd = am->registerAction(m_runToSelectedFunctionAction,
3098 "Debugger.RunToSelectedFunction", cppDebuggercontext);
3099 cmd->setDefaultKeySequence(QKeySequence(
3100 Constants::RUN_TO_SELECTED_FUNCTION_KEY));
3101 cmd->setAttribute(Command::CA_Hide);
3102 // Don't add to menu by default as keeping its enabled state
3103 // and text up-to-date is a lot of hassle.
3104 // debugMenu->addAction(cmd);
3106 cmd = am->registerAction(m_jumpToLineAction,
3107 "Debugger.JumpToLine", cppDebuggercontext);
3108 cmd->setAttribute(Command::CA_Hide);
3109 debugMenu->addAction(cmd);
3111 cmd = am->registerAction(m_returnFromFunctionAction,
3112 "Debugger.ReturnFromFunction", cppDebuggercontext);
3113 cmd->setAttribute(Command::CA_Hide);
3114 debugMenu->addAction(cmd);
3116 cmd = am->registerAction(m_reverseDirectionAction,
3117 Constants::REVERSE, cppDebuggercontext);
3118 cmd->setDefaultKeySequence(QKeySequence(Constants::REVERSE_KEY));
3119 cmd->setAttribute(Command::CA_Hide);
3120 debugMenu->addAction(cmd);
3122 sep = new QAction(this);
3123 sep->setSeparator(true);
3124 cmd = am->registerAction(sep, "Debugger.Sep.Break", globalcontext);
3125 debugMenu->addAction(cmd);
3127 //cmd = am->registerAction(m_snapshotAction,
3128 // "Debugger.Snapshot", cppDebuggercontext);
3129 //cmd->setDefaultKeySequence(QKeySequence(Constants::SNAPSHOT_KEY));
3130 //cmd->setAttribute(Command::CA_Hide);
3131 //debugMenu->addAction(cmd);
3133 cmd = am->registerAction(m_frameDownAction,
3134 "Debugger.FrameDown", cppDebuggercontext);
3135 cmd = am->registerAction(m_frameUpAction,
3136 "Debugger.FrameUp", cppDebuggercontext);
3138 cmd = am->registerAction(action(OperateByInstruction),
3139 Constants::OPERATE_BY_INSTRUCTION, cppDebuggercontext);
3140 cmd->setAttribute(Command::CA_Hide);
3141 debugMenu->addAction(cmd);
3143 cmd = am->registerAction(m_breakAction,
3144 "Debugger.ToggleBreak", globalcontext);
3145 cmd->setDefaultKeySequence(QKeySequence(Constants::TOGGLE_BREAK_KEY));
3146 debugMenu->addAction(cmd);
3147 connect(m_breakAction, SIGNAL(triggered()),
3148 SLOT(toggleBreakpoint()));
3150 sep = new QAction(this);
3151 sep->setSeparator(true);
3152 cmd = am->registerAction(sep, "Debugger.Sep.Watch", globalcontext);
3153 debugMenu->addAction(cmd);
3155 // Don't add '1' to the string as it shows up in the shortcut dialog.
3156 cmd = am->registerAction(m_watchAction1,
3157 "Debugger.AddToWatch", cppeditorcontext);
3158 //cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+D,Ctrl+W")));
3159 debugMenu->addAction(cmd);
3161 // If the CppEditor plugin is there, we want to add something to
3162 // the editor context menu.
3163 if (ActionContainer *editorContextMenu =
3164 am->actionContainer(CppEditor::Constants::M_CONTEXT)) {
3165 cmd = am->registerAction(sep, "Debugger.Sep.Views",
3166 cppDebuggercontext);
3167 editorContextMenu->addAction(cmd);
3168 cmd->setAttribute(Command::CA_Hide);
3170 cmd = am->registerAction(m_watchAction2,
3171 "Debugger.AddToWatch2", cppDebuggercontext);
3172 cmd->action()->setEnabled(true);
3173 editorContextMenu->addAction(cmd);
3174 cmd->setAttribute(Command::CA_Hide);
3175 cmd->setAttribute(Command::CA_NonConfigurable);
3176 // Debugger.AddToWatch is enough.
3179 QList<Core::IOptionsPage *> engineOptionPages;
3180 if (m_cmdLineEnabledEngines & GdbEngineType)
3181 addGdbOptionPages(&engineOptionPages);
3182 addCdbOptionPages(&engineOptionPages);
3184 if (m_cmdLineEnabledEngines & LldbEngineType)
3185 addLldbOptionPages(&engineOptionPages);
3188 //if (m_cmdLineEnabledEngines & ScriptEngineType)
3189 // addScriptOptionPages(&engineOptionPages);
3190 //if (m_cmdLineEnabledEngines & TcfEngineType)
3191 // addTcfOptionPages(&engineOptionPages);
3192 foreach (Core::IOptionsPage *op, engineOptionPages)
3193 m_plugin->addAutoReleasedObject(op);
3194 m_plugin->addAutoReleasedObject(new DebuggingHelperOptionPage);
3196 connect(ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*)),
3197 SLOT(onModeChanged(Core::IMode*)));
3198 connect(ICore::instance(), SIGNAL(coreAboutToOpen()),
3199 SLOT(onCoreAboutToOpen()));
3203 DebugMode *debugMode = new DebugMode;
3204 QWidget *widget = m_mainWindow->createContents(debugMode);
3205 widget->setFocusProxy(EditorManager::instance());
3206 debugMode->setWidget(widget);
3208 m_plugin->addAutoReleasedObject(debugMode);
3215 connect(core, SIGNAL(saveSettingsRequested()), SLOT(writeSettings()));
3218 connect(TextEditorSettings::instance(),
3219 SIGNAL(fontSettingsChanged(TextEditor::FontSettings)),
3220 SLOT(fontSettingsChanged(TextEditor::FontSettings)));
3223 connect(sessionManager(), SIGNAL(sessionLoaded()),
3224 SLOT(sessionLoaded()));
3225 connect(sessionManager(), SIGNAL(aboutToSaveSession()),
3226 SLOT(aboutToSaveSession()));
3227 connect(sessionManager(), SIGNAL(aboutToUnloadSession()),
3228 SLOT(aboutToUnloadSession()));
3229 connect(ProjectExplorerPlugin::instance(), SIGNAL(updateRunActions()),
3230 SLOT(updateDebugActions()));
3233 QObject *editorManager = core->editorManager();
3234 connect(editorManager, SIGNAL(editorOpened(Core::IEditor*)),
3235 SLOT(editorOpened(Core::IEditor*)));
3236 connect(editorManager, SIGNAL(currentEditorChanged(Core::IEditor*)),
3237 SLOT(updateBreakMenuItem(Core::IEditor*)));
3239 // Application interaction
3240 connect(action(SettingsDialog), SIGNAL(triggered()),
3241 SLOT(showSettingsDialog()));
3244 QWidget *toolbarContainer = new QWidget;
3246 QHBoxLayout *hbox = new QHBoxLayout(toolbarContainer);
3248 hbox->setSpacing(0);
3249 hbox->addWidget(toolButton(m_visibleStartAction));
3250 hbox->addWidget(toolButton(m_exitAction));
3251 hbox->addWidget(toolButton(m_nextAction));
3252 hbox->addWidget(toolButton(m_stepAction));
3253 hbox->addWidget(toolButton(m_stepOutAction));
3254 hbox->addWidget(toolButton(action(OperateByInstruction)));
3256 //hbox->addWidget(new Utils::StyledSeparator);
3257 m_reverseToolButton = toolButton(m_reverseDirectionAction);
3258 hbox->addWidget(m_reverseToolButton);
3259 //m_reverseToolButton->hide();
3261 hbox->addWidget(new Utils::StyledSeparator);
3262 hbox->addWidget(new QLabel(tr("Threads:")));
3264 m_threadBox = new QComboBox;
3265 m_threadBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
3266 connect(m_threadBox, SIGNAL(activated(int)), SLOT(selectThread(int)));
3268 hbox->addWidget(m_threadBox);
3269 hbox->addSpacerItem(new QSpacerItem(4, 0));
3270 hbox->addWidget(m_statusLabel, 10);
3272 m_mainWindow->setToolBar(CppLanguage, toolbarContainer);
3274 connect(action(EnableReverseDebugging),
3275 SIGNAL(valueChanged(QVariant)),
3276 SLOT(enableReverseDebuggingTriggered(QVariant)));
3281 connect(sessionManager(),
3282 SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
3283 SLOT(onCurrentProjectChanged(ProjectExplorer::Project*)));
3285 QTC_CHECK(m_coreSettings);
3286 m_globalDebuggerOptions->fromSettings(m_coreSettings);
3287 m_watchersWindow->setVisible(false);
3288 m_returnWindow->setVisible(false);
3290 // time gdb -i mi -ex 'b debuggerplugin.cpp:800' -ex r -ex q bin/qtcreator.bin
3291 if (!m_scheduledStarts.isEmpty())
3292 QTimer::singleShot(0, this, SLOT(runScheduled()));
3295 Utils::SavedAction *DebuggerPluginPrivate::action(int code) const
3297 return m_debuggerSettings->item(code);
3300 bool DebuggerPluginPrivate::boolSetting(int code) const
3302 return m_debuggerSettings->item(code)->value().toBool();
3305 QString DebuggerPluginPrivate::stringSetting(int code) const
3307 return m_debuggerSettings->item(code)->value().toString();
3310 void DebuggerPluginPrivate::showModuleSymbols(const QString &moduleName,
3311 const Symbols &symbols)
3313 QTreeWidget *w = new QTreeWidget;
3314 w->setColumnCount(5);
3315 w->setRootIsDecorated(false);
3316 w->setAlternatingRowColors(true);
3317 w->setSortingEnabled(true);
3318 w->setObjectName("Symbols." + moduleName);
3320 header.append(tr("Symbol"));
3321 header.append(tr("Address"));
3322 header.append(tr("Code"));
3323 header.append(tr("Section"));
3324 header.append(tr("Name"));
3325 w->setHeaderLabels(header);
3326 w->setWindowTitle(tr("Symbols in \"%1\"").arg(moduleName));
3327 foreach (const Symbol &s, symbols) {
3328 QTreeWidgetItem *it = new QTreeWidgetItem;
3329 it->setData(0, Qt::DisplayRole, s.name);
3330 it->setData(1, Qt::DisplayRole, s.address);
3331 it->setData(2, Qt::DisplayRole, s.state);
3332 it->setData(3, Qt::DisplayRole, s.section);
3333 it->setData(4, Qt::DisplayRole, s.demangled);
3334 w->addTopLevelItem(it);
3339 void DebuggerPluginPrivate::aboutToShutdown()
3341 m_plugin->removeObject(this);
3342 disconnect(sessionManager(),
3343 SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
3347 } // namespace Internal
3350 ///////////////////////////////////////////////////////////////////////
3354 ///////////////////////////////////////////////////////////////////////
3356 using namespace Debugger::Internal;
3359 \class Debugger::DebuggerPlugin
3361 This is the "external" interface of the debugger plugin that's visible
3362 from Qt Creator core. The internal interface to global debugger
3363 functionality that is used by debugger views and debugger engines
3364 is DebuggerCore, implemented in DebuggerPluginPrivate. */
3366 DebuggerPlugin::DebuggerPlugin()
3368 theDebuggerCore = new DebuggerPluginPrivate(this);
3371 DebuggerPlugin::~DebuggerPlugin()
3373 delete theDebuggerCore;
3374 theDebuggerCore = 0;
3377 bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMessage)
3379 ICore *core = ICore::instance();
3380 QTC_ASSERT(core, return true);
3383 const Context globalcontext(CC::C_GLOBAL);
3385 Core::ActionManager *am = core->actionManager();
3386 ActionContainer *mstart = am->actionContainer(PE::M_DEBUG_STARTDEBUGGING);
3388 mstart->appendGroup(Constants::G_START_CPP);
3389 mstart->appendGroup(Constants::G_START_QML);
3391 // add cpp separator
3392 QAction *sep = new QAction(mstart);
3393 sep->setSeparator(true);
3394 Command *cmd = am->registerAction(sep,
3395 "Debugger.Start.Cpp", globalcontext);
3396 mstart->addAction(cmd, Constants::G_START_CPP);
3398 return theDebuggerCore->initialize(arguments, errorMessage);
3401 ExtensionSystem::IPlugin::ShutdownFlag DebuggerPlugin::aboutToShutdown()
3403 theDebuggerCore->aboutToShutdown();
3404 return SynchronousShutdown;
3407 void DebuggerPlugin::remoteCommand(const QStringList &options,
3408 const QStringList &list)
3410 theDebuggerCore->remoteCommand(options, list);
3413 DebuggerRunControl *DebuggerPlugin::createDebugger
3414 (const DebuggerStartParameters &sp, RunConfiguration *rc)
3416 return theDebuggerCore->createDebugger(sp, rc);
3419 void DebuggerPlugin::startDebugger(RunControl *runControl)
3421 theDebuggerCore->startDebugger(runControl);
3424 void DebuggerPlugin::extensionsInitialized()
3426 theDebuggerCore->extensionsInitialized();
3429 bool DebuggerPlugin::isActiveDebugLanguage(int language)
3431 return theDebuggerCore->isActiveDebugLanguage(language);
3434 DebuggerMainWindow *DebuggerPlugin::mainWindow()
3436 return theDebuggerCore->m_mainWindow;
3439 QAction *DebuggerPlugin::visibleDebugAction()
3441 return theDebuggerCore->m_visibleStartAction;
3444 } // namespace Debugger
3446 #include "debuggerplugin.moc"
3448 Q_EXPORT_PLUGIN(Debugger::DebuggerPlugin)