2 * Copyright Johannes Sixt
3 * This file is licensed under the GNU General Public License Version 2.
4 * See the file COPYING in the toplevel directory of the source directory.
8 #include <klocale.h> /* i18n */
9 #include <kmessagebox.h>
11 #include <kstatusbar.h>
12 #include <kiconloader.h>
13 #include <kstdaccel.h>
14 #include <kstdaction.h>
16 #include <kpopupmenu.h>
17 #include <kfiledialog.h>
19 #include <kkeydialog.h>
20 #include <kanimwidget.h>
23 #include <qfileinfo.h>
24 #include "dbgmainwnd.h"
26 #include "commandids.h"
29 #include "threadlist.h"
30 #include "memwindow.h"
32 #include "procattach.h"
33 #include "dbgdriver.h"
40 DebuggerMainWnd::DebuggerMainWnd(const char* name
) :
41 KDockMainWindow(0, name
),
46 KDockWidget
* dw0
= createDockWidget("Source", p
, 0, i18n("Source"));
47 m_filesWindow
= new WinStack(dw0
, "files");
48 dw0
->setWidget(m_filesWindow
);
49 dw0
->setDockSite(KDockWidget::DockCorner
);
50 dw0
->setEnableDocking(KDockWidget::DockNone
);
52 setMainDockWidget(dw0
);
54 KDockWidget
* dw1
= createDockWidget("Stack", p
, 0, i18n("Stack"));
55 m_btWindow
= new QListBox(dw1
, "backtrace");
56 dw1
->setWidget(m_btWindow
);
57 KDockWidget
* dw2
= createDockWidget("Locals", p
, 0, i18n("Locals"));
58 m_localVariables
= new ExprWnd(dw2
, i18n("Variable"), "locals");
59 dw2
->setWidget(m_localVariables
);
60 KDockWidget
* dw3
= createDockWidget("Watches", p
, 0, i18n("Watches"));
61 m_watches
= new WatchWindow(dw3
, "watches");
62 dw3
->setWidget(m_watches
);
63 KDockWidget
* dw4
= createDockWidget("Registers", p
, 0, i18n("Registers"));
64 m_registers
= new RegisterView(dw4
, "registers");
65 dw4
->setWidget(m_registers
);
66 KDockWidget
* dw5
= createDockWidget("Breakpoints", p
, 0, i18n("Breakpoints"));
67 m_bpTable
= new BreakpointTable(dw5
, "breakpoints");
68 dw5
->setWidget(m_bpTable
);
69 KDockWidget
* dw6
= createDockWidget("Output", p
, 0, i18n("Output"));
70 m_ttyWindow
= new TTYWindow(dw6
, "output");
71 dw6
->setWidget(m_ttyWindow
);
72 KDockWidget
* dw7
= createDockWidget("Threads", p
, 0, i18n("Threads"));
73 m_threads
= new ThreadList(dw7
, "threads");
74 dw7
->setWidget(m_threads
);
75 KDockWidget
* dw8
= createDockWidget("Memory", p
, 0, i18n("Memory"));
76 m_memoryWindow
= new MemoryWindow(dw8
, "memory");
77 dw8
->setWidget(m_memoryWindow
);
79 setupDebugger(this, m_localVariables
, m_watches
->watchVariables(), m_btWindow
);
80 m_bpTable
->setDebugger(m_debugger
);
81 m_memoryWindow
->setDebugger(m_debugger
);
84 initToolbar(); // kind of obsolete?
86 connect(m_watches
, SIGNAL(addWatch()), SLOT(slotAddWatch()));
87 connect(m_watches
, SIGNAL(deleteWatch()), m_debugger
, SLOT(slotDeleteWatch()));
88 connect(m_watches
, SIGNAL(textDropped(const QString
&)), SLOT(slotAddWatch(const QString
&)));
90 KAction
* windowMenu
= actionCollection()->action("window");
91 m_filesWindow
->setWindowMenu(static_cast<KActionMenu
*>(windowMenu
)->popupMenu());
92 connect(&m_filesWindow
->m_findDlg
, SIGNAL(closed()), SLOT(updateUI()));
93 connect(m_filesWindow
, SIGNAL(newFileLoaded()),
94 SLOT(slotNewFileLoaded()));
95 connect(m_filesWindow
, SIGNAL(toggleBreak(const QString
&,int,const DbgAddr
&,bool)),
96 this, SLOT(slotToggleBreak(const QString
&,int,const DbgAddr
&,bool)));
97 connect(m_filesWindow
, SIGNAL(enadisBreak(const QString
&,int,const DbgAddr
&)),
98 this, SLOT(slotEnaDisBreak(const QString
&,int,const DbgAddr
&)));
99 connect(m_debugger
, SIGNAL(activateFileLine(const QString
&,int,const DbgAddr
&)),
100 m_filesWindow
, SLOT(activate(const QString
&,int,const DbgAddr
&)));
101 connect(m_debugger
, SIGNAL(executableUpdated()),
102 m_filesWindow
, SLOT(reloadAllFiles()));
103 connect(m_debugger
, SIGNAL(updatePC(const QString
&,int,const DbgAddr
&,int)),
104 m_filesWindow
, SLOT(updatePC(const QString
&,int,const DbgAddr
&,int)));
105 // value popup communication
106 connect(m_filesWindow
, SIGNAL(initiateValuePopup(const QString
&)),
107 m_debugger
, SLOT(slotValuePopup(const QString
&)));
108 connect(m_debugger
, SIGNAL(valuePopup(const QString
&)),
109 m_filesWindow
, SLOT(slotShowValueTip(const QString
&)));
111 connect(m_filesWindow
, SIGNAL(disassemble(const QString
&, int)),
112 m_debugger
, SLOT(slotDisassemble(const QString
&, int)));
113 connect(m_debugger
, SIGNAL(disassembled(const QString
&,int,const QList
<DisassembledCode
>&)),
114 m_filesWindow
, SLOT(slotDisassembled(const QString
&,int,const QList
<DisassembledCode
>&)));
115 connect(m_filesWindow
, SIGNAL(moveProgramCounter(const QString
&,int,const DbgAddr
&)),
116 m_debugger
, SLOT(setProgramCounter(const QString
&,int,const DbgAddr
&)));
118 connect(m_debugger
, SIGNAL(programStopped()), SLOT(slotProgramStopped()));
119 connect(&m_backTimer
, SIGNAL(timeout()), SLOT(slotBackTimer()));
121 connect(this, SIGNAL(setTabWidth(int)), m_filesWindow
, SIGNAL(setTabWidth(int)));
124 connect(m_filesWindow
, SIGNAL(fileChanged()), SLOT(slotFileChanged()));
125 connect(m_filesWindow
, SIGNAL(lineChanged()), SLOT(slotLineChanged()));
127 // connect breakpoint table
128 connect(m_bpTable
, SIGNAL(activateFileLine(const QString
&,int,const DbgAddr
&)),
129 m_filesWindow
, SLOT(activate(const QString
&,int,const DbgAddr
&)));
130 connect(m_debugger
, SIGNAL(updateUI()), m_bpTable
, SLOT(updateUI()));
131 connect(m_debugger
, SIGNAL(breakpointsChanged()), m_bpTable
, SLOT(updateBreakList()));
132 connect(m_debugger
, SIGNAL(breakpointsChanged()), m_bpTable
, SLOT(updateUI()));
134 connect(m_debugger
, SIGNAL(registersChanged(QList
<RegisterInfo
>&)),
135 m_registers
, SLOT(updateRegisters(QList
<RegisterInfo
>&)));
137 connect(m_debugger
, SIGNAL(memoryDumpChanged(const QString
&, QList
<MemoryDump
>&)),
138 m_memoryWindow
, SLOT(slotNewMemoryDump(const QString
&, QList
<MemoryDump
>&)));
139 connect(m_debugger
, SIGNAL(saveProgramSpecific(KConfigBase
*)),
140 m_memoryWindow
, SLOT(saveProgramSpecific(KConfigBase
*)));
141 connect(m_debugger
, SIGNAL(restoreProgramSpecific(KConfigBase
*)),
142 m_memoryWindow
, SLOT(restoreProgramSpecific(KConfigBase
*)));
145 connect(m_debugger
, SIGNAL(threadsChanged(QList
<ThreadInfo
>&)),
146 m_threads
, SLOT(updateThreads(QList
<ThreadInfo
>&)));
147 connect(m_threads
, SIGNAL(setThread(int)),
148 m_debugger
, SLOT(setThread(int)));
150 // view menu changes when docking state changes
151 connect(dockManager
, SIGNAL(change()), SLOT(updateUI()));
153 // popup menu of the local variables window
154 connect(m_localVariables
, SIGNAL(contextMenuRequested(QListViewItem
*, const QPoint
&, int)),
155 this, SLOT(slotLocalsPopup(QListViewItem
*, const QPoint
&)));
157 restoreSettings(kapp
->config());
160 m_bpTable
->updateUI();
164 DebuggerMainWnd::~DebuggerMainWnd()
166 saveSettings(kapp
->config());
167 // must delete m_debugger early since it references our windows
171 delete m_memoryWindow
;
177 delete m_localVariables
;
179 delete m_filesWindow
;
182 void DebuggerMainWnd::initKAction()
185 KAction
* open
= KStdAction::open(this, SLOT(slotFileOpen()),
187 open
->setText(i18n("&Open Source..."));
188 (void)new KAction(i18n("&Reload Source"), "reload", 0, m_filesWindow
,
189 SLOT(slotFileReload()), actionCollection(),
191 (void)new KAction(i18n("&Executable..."), "execopen", 0, this,
192 SLOT(slotFileExe()), actionCollection(),
194 m_recentExecAction
= new KRecentFilesAction(i18n("Recent E&xecutables"), 0,
195 this, SLOT(slotRecentExec(const KURL
&)),
196 actionCollection(), "file_executable_recent");
197 (void)new KAction(i18n("&Core dump..."), 0, this, SLOT(slotFileCore()),
198 actionCollection(), "file_core_dump");
199 KStdAction::quit(this, SLOT(slotFileQuit()), actionCollection());
202 (void)new KAction(i18n("This &Program..."), 0, this,
203 SLOT(slotFileProgSettings()), actionCollection(),
205 (void)new KAction(i18n("&Global Options..."), 0, this,
206 SLOT(slotFileGlobalSettings()), actionCollection(),
208 KStdAction::keyBindings(this, SLOT(slotConfigureKeys()), actionCollection());
209 KStdAction::showToolbar(this, SLOT(slotViewToolbar()), actionCollection());
210 KStdAction::showStatusbar(this, SLOT(slotViewStatusbar()), actionCollection());
213 (void)new KToggleAction(i18n("&Find"), "find", CTRL
+Key_F
, m_filesWindow
,
214 SLOT(slotViewFind()), actionCollection(),
216 i18n("Source &code");
217 struct { QString text
; QWidget
* w
; QString id
; } dw
[] = {
218 { i18n("Stac&k"), m_btWindow
, "view_stack"},
219 { i18n("&Locals"), m_localVariables
, "view_locals"},
220 { i18n("&Watched expressions"), m_watches
, "view_watched_expressions"},
221 { i18n("&Registers"), m_registers
, "view_registers"},
222 { i18n("&Breakpoints"), m_bpTable
, "view_breakpoints"},
223 { i18n("T&hreads"), m_threads
, "view_threads"},
224 { i18n("&Output"), m_ttyWindow
, "view_output"},
225 { i18n("&Memory"), m_memoryWindow
, "view_memory"}
227 for (unsigned i
= 0; i
< sizeof(dw
)/sizeof(dw
[0]); i
++) {
228 KDockWidget
* d
= dockParent(dw
[i
].w
);
229 (void)new KToggleAction(dw
[i
].text
, 0, d
, SLOT(changeHideShowState()),
230 actionCollection(), dw
[i
].id
);
235 KAction
* a
= new KAction(i18n("&Run"), "pgmrun", Key_F5
, m_debugger
,
236 SLOT(programRun()), actionCollection(), "exec_run");
237 connect(a
, SIGNAL(activated()), this, SLOT(intoBackground()));
238 a
= new KAction(i18n("Step &into"), "pgmstep", Key_F8
, m_debugger
,
239 SLOT(programStep()), actionCollection(),
241 connect(a
, SIGNAL(activated()), this, SLOT(intoBackground()));
242 a
= new KAction(i18n("Step &over"), "pgmnext", Key_F10
, m_debugger
,
243 SLOT(programNext()), actionCollection(),
245 connect(a
, SIGNAL(activated()), this, SLOT(intoBackground()));
246 a
= new KAction(i18n("Step o&ut"), "pgmfinish", Key_F6
, m_debugger
,
247 SLOT(programFinish()), actionCollection(),
249 connect(a
, SIGNAL(activated()), this, SLOT(intoBackground()));
250 a
= new KAction(i18n("Run to &cursor"), Key_F7
, this,
251 SLOT(slotExecUntil()), actionCollection(),
252 "exec_run_to_cursor");
253 connect(a
, SIGNAL(activated()), this, SLOT(intoBackground()));
254 a
= new KAction(i18n("Step i&nto by instruction"), "pgmstepi",
255 SHIFT
+Key_F8
, m_debugger
, SLOT(programStepi()),
256 actionCollection(), "exec_step_into_by_insn");
257 connect(a
, SIGNAL(activated()), this, SLOT(intoBackground()));
258 a
= new KAction(i18n("Step o&ver by instruction"), "pgmnexti",
259 SHIFT
+Key_F10
, m_debugger
, SLOT(programNexti()),
260 actionCollection(), "exec_step_over_by_insn");
261 connect(a
, SIGNAL(activated()), this, SLOT(intoBackground()));
262 (void)new KAction(i18n("&Program counter to current line"), 0,
263 m_filesWindow
, SLOT(slotMoveProgramCounter()),
264 actionCollection(), "exec_movepc");
265 (void)new KAction(i18n("&Break"), 0, m_debugger
,
266 SLOT(programBreak()), actionCollection(),
268 (void)new KAction(i18n("&Kill"), 0, m_debugger
,
269 SLOT(programKill()), actionCollection(),
271 (void)new KAction(i18n("Re&start"), 0, m_debugger
,
272 SLOT(programRunAgain()), actionCollection(),
274 (void)new KAction(i18n("A&ttach..."), 0, this,
275 SLOT(slotExecAttach()), actionCollection(),
277 (void)new KAction(i18n("&Arguments..."), 0, this,
278 SLOT(slotExecArgs()), actionCollection(),
282 (void)new KAction(i18n("Set/Clear &breakpoint"), "brkpt", Key_F9
,
283 m_filesWindow
, SLOT(slotBrkptSet()), actionCollection(),
285 (void)new KAction(i18n("Set &temporary breakpoint"), SHIFT
+Key_F9
,
286 m_filesWindow
, SLOT(slotBrkptSetTemp()), actionCollection(),
287 "breakpoint_set_temporary");
288 (void)new KAction(i18n("&Enable/Disable breakpoint"), CTRL
+Key_F9
,
289 m_filesWindow
, SLOT(slotBrkptEnable()), actionCollection(),
290 "breakpoint_enable");
292 // only in popup menus
293 (void)new KAction(i18n("Watch Expression"), 0, this,
294 SLOT(slotLocalsToWatch()), actionCollection(),
296 (void)new KAction(i18n("Edit Value"), Key_F2
, this,
297 SLOT(slotEditValue()), actionCollection(),
300 (void)new KActionMenu(i18n("&Window"), actionCollection(), "window");
302 // all actions force an UI update
303 QValueList
<KAction
*> actions
= actionCollection()->actions();
304 QValueList
<KAction
*>::Iterator it
= actions
.begin();
305 for (; it
!= actions
.end(); ++it
) {
306 connect(*it
, SIGNAL(activated()), this, SLOT(updateUI()));
309 createGUI("kdbgui.rc");
312 void DebuggerMainWnd::initToolbar()
314 KToolBar
* toolbar
= toolBar("mainToolBar");
315 toolbar
->setBarPos(KToolBar::Top
);
316 //moveToolBar(toolbar);
318 toolbar
->insertAnimatedWidget(ID_STATUS_BUSY
,
319 actionCollection()->action("exec_break"), SLOT(activate()),
321 toolbar
->alignItemRight(ID_STATUS_BUSY
, true);
322 m_animRunning
= false;
324 KStatusBar
* statusbar
= statusBar();
325 statusbar
->insertItem(m_statusActive
, ID_STATUS_ACTIVE
);
326 m_lastActiveStatusText
= m_statusActive
;
327 statusbar
->insertItem(i18n("Line 00000"), ID_STATUS_LINENO
);
328 statusbar
->insertItem("", ID_STATUS_MSG
); /* message pane */
330 // reserve some translations
336 * We must override KTMainWindow's handling of close events since we have
337 * only one toplevel window, which lives on the stack (which KTMainWindow
338 * can't live with :-( )
340 void DebuggerMainWnd::closeEvent(QCloseEvent
* e
)
342 clearWFlags(WDestructiveClose
);
344 if (m_debugger
!= 0) {
345 m_debugger
->shutdown();
353 // instance properties
354 void DebuggerMainWnd::saveProperties(KConfig
* config
)
356 // session management
357 QString executable
= "";
358 if (m_debugger
!= 0) {
359 executable
= m_debugger
->executable();
361 config
->writeEntry("executable", executable
);
364 void DebuggerMainWnd::readProperties(KConfig
* config
)
366 // session management
367 QString execName
= config
->readEntry("executable");
369 TRACE("readProperties: executable=" + execName
);
370 if (!execName
.isEmpty()) {
371 debugProgram(execName
, "");
375 const char WindowGroup
[] = "Windows";
376 const char RecentExecutables
[] = "RecentExecutables";
377 const char LastSession
[] = "LastSession";
379 void DebuggerMainWnd::saveSettings(KConfig
* config
)
381 KConfigGroupSaver
g(config
, WindowGroup
);
383 writeDockConfig(config
);
384 fixDockConfig(config
, false); // downgrade
386 m_recentExecAction
->saveEntries(config
, RecentExecutables
);
388 KConfigGroupSaver
g2(config
, LastSession
);
389 config
->writeEntry("Width0Locals", m_localVariables
->columnWidth(0));
390 config
->writeEntry("Width0Watches", m_watches
->columnWidth(0));
392 DebuggerMainWndBase::saveSettings(config
);
395 void DebuggerMainWnd::restoreSettings(KConfig
* config
)
397 KConfigGroupSaver
g(config
, WindowGroup
);
399 fixDockConfig(config
, true); // upgrade
400 readDockConfig(config
);
402 // Workaround bug #87787: KDockManager stores the titles of the KDockWidgets
403 // in the config files, although they are localized:
404 // If the user changes the language, the titles remain in the previous language.
405 struct { QString text
; QWidget
* w
; } dw
[] = {
406 { i18n("Stack"), m_btWindow
},
407 { i18n("Locals"), m_localVariables
},
408 { i18n("Watches"), m_watches
},
409 { i18n("Registers"), m_registers
},
410 { i18n("Breakpoints"), m_bpTable
},
411 { i18n("Threads"), m_threads
},
412 { i18n("Output"), m_ttyWindow
},
413 { i18n("Memory"), m_memoryWindow
}
415 for (int i
= 0; i
< int(sizeof(dw
)/sizeof(dw
[0])); i
++)
417 KDockWidget
* w
= dockParent(dw
[i
].w
);
418 w
->setTabPageLabel(dw
[i
].text
);
419 // this actually changes the captions in the tabs:
420 QEvent
ev(QEvent::CaptionChange
);
424 m_recentExecAction
->loadEntries(config
, RecentExecutables
);
426 KConfigGroupSaver
g2(config
, LastSession
);
428 w
= config
->readNumEntry("Width0Locals", -1);
429 if (w
>= 0 && w
< 30000)
430 m_localVariables
->setColumnWidth(0, w
);
431 w
= config
->readNumEntry("Width0Watches", -1);
432 if (w
>= 0 && w
< 30000)
433 m_watches
->setColumnWidth(0, w
);
435 DebuggerMainWndBase::restoreSettings(config
);
437 emit
setTabWidth(m_tabWidth
);
440 void DebuggerMainWnd::updateUI()
442 KToggleAction
* viewFind
=
443 static_cast<KToggleAction
*>(actionCollection()->action("view_find"));
444 viewFind
->setChecked(m_filesWindow
->m_findDlg
.isVisible());
445 viewFind
->setEnabled(m_filesWindow
->hasWindows());
446 actionCollection()->action("breakpoint_set")->setEnabled(m_debugger
->canChangeBreakpoints());
447 actionCollection()->action("breakpoint_set_temporary")->setEnabled(m_debugger
->canChangeBreakpoints());
448 actionCollection()->action("breakpoint_enable")->setEnabled(m_debugger
->canChangeBreakpoints());
449 dockUpdateHelper("view_breakpoints", m_bpTable
);
450 dockUpdateHelper("view_stack", m_btWindow
);
451 dockUpdateHelper("view_locals", m_localVariables
);
452 dockUpdateHelper("view_watched_expressions", m_watches
);
453 dockUpdateHelper("view_registers", m_registers
);
454 dockUpdateHelper("view_threads", m_threads
);
455 dockUpdateHelper("view_memory", m_memoryWindow
);
456 dockUpdateHelper("view_output", m_ttyWindow
);
458 // AB: maybe in mainwndbase.cpp?
459 actionCollection()->action("file_executable")->setEnabled(m_debugger
->isIdle());
460 actionCollection()->action("settings_program")->setEnabled(m_debugger
->haveExecutable());
461 actionCollection()->action("file_core_dump")->setEnabled(m_debugger
->canStart());
462 actionCollection()->action("exec_step_into")->setEnabled(m_debugger
->canSingleStep());
463 actionCollection()->action("exec_step_into_by_insn")->setEnabled(m_debugger
->canSingleStep());
464 actionCollection()->action("exec_step_over")->setEnabled(m_debugger
->canSingleStep());
465 actionCollection()->action("exec_step_over_by_insn")->setEnabled(m_debugger
->canSingleStep());
466 actionCollection()->action("exec_step_out")->setEnabled(m_debugger
->canSingleStep());
467 actionCollection()->action("exec_run_to_cursor")->setEnabled(m_debugger
->canSingleStep());
468 actionCollection()->action("exec_movepc")->setEnabled(m_debugger
->canSingleStep());
469 actionCollection()->action("exec_restart")->setEnabled(m_debugger
->canSingleStep());
470 actionCollection()->action("exec_attach")->setEnabled(m_debugger
->isReady());
471 actionCollection()->action("exec_run")->setEnabled(m_debugger
->canStart() || m_debugger
->canSingleStep());
472 actionCollection()->action("exec_kill")->setEnabled(m_debugger
->haveExecutable() && m_debugger
->isProgramActive());
473 actionCollection()->action("exec_break")->setEnabled(m_debugger
->isProgramRunning());
474 actionCollection()->action("exec_arguments")->setEnabled(m_debugger
->haveExecutable());
475 actionCollection()->action("edit_value")->setEnabled(m_debugger
->canSingleStep());
478 KAnimWidget
* w
= toolBar("mainToolBar")->animatedWidget(ID_STATUS_BUSY
);
479 if (m_debugger
->isIdle()) {
482 m_animRunning
= false;
485 if (!m_animRunning
) {
487 m_animRunning
= true;
493 if (m_debugger
->isProgramActive())
494 newStatus
= m_statusActive
;
495 if (newStatus
!= m_lastActiveStatusText
) {
496 statusBar()->changeItem(newStatus
, ID_STATUS_ACTIVE
);
497 m_lastActiveStatusText
= newStatus
;
499 // line number is updated in slotLineChanged
502 void DebuggerMainWnd::dockUpdateHelper(QString action
, QWidget
* w
)
504 KToggleAction
* item
=
505 static_cast<KToggleAction
*>(actionCollection()->action(action
));
506 bool canChange
= canChangeDockVisibility(w
);
507 item
->setEnabled(canChange
);
508 item
->setChecked(canChange
&& isDockVisible(w
));
511 void DebuggerMainWnd::updateLineItems()
513 m_filesWindow
->updateLineItems(m_debugger
);
516 void DebuggerMainWnd::slotAddWatch()
518 if (m_debugger
!= 0) {
519 QString t
= m_watches
->watchText();
520 m_debugger
->addWatch(t
);
524 void DebuggerMainWnd::slotAddWatch(const QString
& text
)
526 if (m_debugger
!= 0) {
527 m_debugger
->addWatch(text
);
531 void DebuggerMainWnd::slotFileChanged()
536 if (m_debugger
->haveExecutable()) {
537 // basename part of executable
538 QString executable
= m_debugger
->executable();
539 const char* execBase
= executable
.data();
540 int lastSlash
= executable
.findRev('/');
542 execBase
+= lastSlash
+ 1;
547 bool anyWindows
= m_filesWindow
->activeLine(file
, line
);
548 updateLineStatus(anyWindows
? line
: -1);
557 void DebuggerMainWnd::slotLineChanged()
561 bool anyWindows
= m_filesWindow
->activeLine(file
, line
);
562 updateLineStatus(anyWindows
? line
: -1);
565 void DebuggerMainWnd::slotNewFileLoaded()
567 // updates program counter in the new file
569 m_filesWindow
->updateLineItems(m_debugger
);
572 void DebuggerMainWnd::updateLineStatus(int lineNo
)
575 statusBar()->changeItem("", ID_STATUS_LINENO
);
578 strLine
.sprintf(i18n("Line %d"), lineNo
+ 1);
579 statusBar()->changeItem(strLine
, ID_STATUS_LINENO
);
583 KDockWidget
* DebuggerMainWnd::dockParent(QWidget
* w
)
585 while ((w
= w
->parentWidget()) != 0) {
586 if (w
->isA("KDockWidget"))
587 return static_cast<KDockWidget
*>(w
);
592 bool DebuggerMainWnd::isDockVisible(QWidget
* w
)
594 KDockWidget
* d
= dockParent(w
);
595 return d
!= 0 && d
->mayBeHide();
598 bool DebuggerMainWnd::canChangeDockVisibility(QWidget
* w
)
600 KDockWidget
* d
= dockParent(w
);
601 return d
!= 0 && (d
->mayBeHide() || d
->mayBeShow());
604 // upgrades the entries from version 0.0.4 to 0.0.5 and back
605 void DebuggerMainWnd::fixDockConfig(KConfig
* c
, bool upgrade
)
607 static const char dockGroup
[] = "dock_setting_default";
608 if (!c
->hasGroup(dockGroup
))
611 static const char oldVersion
[] = "0.0.4";
612 static const char newVersion
[] = "0.0.5";
613 const char* from
= upgrade
? oldVersion
: newVersion
;
614 const char* to
= upgrade
? newVersion
: oldVersion
;
615 QMap
<QString
,QString
> e
= c
->entryMap(dockGroup
);
616 if (e
["Version"] != from
)
619 KConfigGroupSaver
g(c
, dockGroup
);
620 c
->writeEntry("Version", to
);
621 TRACE(upgrade
? "upgrading dockconfig" : "downgrading dockconfig");
623 // turn all orientation entries from 0 to 1 and from 1 to 0
624 QMap
<QString
,QString
>::Iterator i
;
625 for (i
= e
.begin(); i
!= e
.end(); ++i
)
627 if (i
.key().right(12) == ":orientation") {
628 TRACE("upgrading " + i
.key() + " old value: " + *i
);
629 int orientation
= c
->readNumEntry(i
.key(), -1);
630 if (orientation
>= 0) { // paranoia
631 c
->writeEntry(i
.key(), 1 - orientation
);
637 TTYWindow
* DebuggerMainWnd::ttyWindow()
642 bool DebuggerMainWnd::debugProgram(const QString
& exe
, QCString lang
)
644 // check the file name
647 bool success
= fi
.isFile();
650 QString msg
= i18n("`%1' is not a file or does not exist");
651 KMessageBox::sorry(this, msg
.arg(exe
));
655 success
= DebuggerMainWndBase::debugProgram(fi
.absFilePath(), lang
, this);
660 m_recentExecAction
->addURL(KURL(fi
.absFilePath()));
662 // keep the directory
663 m_lastDirectory
= fi
.dirPath(true);
664 m_filesWindow
->setExtraDirectory(m_lastDirectory
);
668 m_recentExecAction
->removeURL(KURL(fi
.absFilePath()));
674 void DebuggerMainWnd::slotNewStatusMsg()
676 newStatusMsg(statusBar());
679 void DebuggerMainWnd::slotFileGlobalSettings()
681 int oldTabWidth
= m_tabWidth
;
683 doGlobalOptions(this);
685 if (m_tabWidth
!= oldTabWidth
) {
686 emit
setTabWidth(m_tabWidth
);
690 void DebuggerMainWnd::slotDebuggerStarting()
692 DebuggerMainWndBase::slotDebuggerStarting();
695 void DebuggerMainWnd::slotToggleBreak(const QString
& fileName
, int lineNo
,
696 const DbgAddr
& address
, bool temp
)
698 // lineNo is zero-based
699 if (m_debugger
!= 0) {
700 m_debugger
->setBreakpoint(fileName
, lineNo
, address
, temp
);
704 void DebuggerMainWnd::slotEnaDisBreak(const QString
& fileName
, int lineNo
,
705 const DbgAddr
& address
)
707 // lineNo is zero-based
708 if (m_debugger
!= 0) {
709 m_debugger
->enableDisableBreakpoint(fileName
, lineNo
, address
);
713 QString
DebuggerMainWnd::createOutputWindow()
715 QString tty
= DebuggerMainWndBase::createOutputWindow();
716 if (!tty
.isEmpty()) {
717 connect(m_outputTermProc
, SIGNAL(processExited(KProcess
*)),
718 SLOT(slotTermEmuExited()));
723 void DebuggerMainWnd::slotTermEmuExited()
725 shutdownTermWindow();
728 void DebuggerMainWnd::slotProgramStopped()
730 // when the program stopped, move the window to the foreground
731 if (m_popForeground
) {
732 // unfortunately, this requires quite some force to work :-(
733 KWin::raiseWindow(winId());
734 KWin::forceActiveWindow(winId());
739 void DebuggerMainWnd::intoBackground()
741 if (m_popForeground
) {
742 m_backTimer
.start(m_backTimeout
, true); /* single-shot */
746 void DebuggerMainWnd::slotBackTimer()
751 void DebuggerMainWnd::slotRecentExec(const KURL
& url
)
753 QString exe
= url
.path();
754 debugProgram(exe
, "");
757 QString
DebuggerMainWnd::makeSourceFilter()
760 f
= m_sourceFilter
+ " " + m_headerFilter
+ i18n("|All source files\n");
761 f
+= m_sourceFilter
+ i18n("|Source files\n");
762 f
+= m_headerFilter
+ i18n("|Header files\n");
763 f
+= i18n("*|All files");
768 * Pop up the context menu in the locals window
770 void DebuggerMainWnd::slotLocalsPopup(QListViewItem
*, const QPoint
& pt
)
773 static_cast<QPopupMenu
*>(factory()->container("popup_locals", this));
777 if (popup
->isVisible()) {
785 * Copies the currently selected item to the watch window.
787 void DebuggerMainWnd::slotLocalsToWatch()
789 VarTree
* item
= m_localVariables
->selectedItem();
791 if (item
!= 0 && m_debugger
!= 0) {
792 QString text
= item
->computeExpr();
793 m_debugger
->addWatch(text
);
798 * Starts editing a value in a value display
800 void DebuggerMainWnd::slotEditValue()
802 // does one of the value trees have the focus
803 QWidget
* f
= kapp
->focusWidget();
805 if (f
== m_localVariables
) {
806 wnd
= m_localVariables
;
807 } else if (f
== m_watches
->watchVariables()) {
808 wnd
= m_watches
->watchVariables();
813 if (m_localVariables
->isEditing() ||
814 m_watches
->watchVariables()->isEditing())
816 return; /* don't edit twice */
819 VarTree
* expr
= wnd
->currentItem();
820 if (expr
!= 0 && m_debugger
!= 0 && m_debugger
->canSingleStep())
823 // determine the text to edit
824 QString text
= m_debugger
->driver()->editableValue(expr
);
825 wnd
->editValue(expr
, text
);
829 void DebuggerMainWnd::slotFileOpen()
831 // start browsing in the active file's directory
832 // fall back to last used directory (executable)
833 QString dir
= m_lastDirectory
;
834 QString fileName
= m_filesWindow
->activeFileName();
835 if (!fileName
.isEmpty()) {
836 QFileInfo
fi(fileName
);
840 fileName
= myGetFileName(i18n("Open"),
842 makeSourceFilter(), this);
844 if (!fileName
.isEmpty())
846 QFileInfo
fi(fileName
);
847 m_lastDirectory
= fi
.dirPath();
848 m_filesWindow
->setExtraDirectory(m_lastDirectory
);
849 m_filesWindow
->activateFile(fileName
);
853 void DebuggerMainWnd::slotFileQuit()
855 if (m_debugger
!= 0) {
856 m_debugger
->shutdown();
861 void DebuggerMainWnd::slotFileExe()
863 if (m_debugger
->isIdle())
865 // open a new executable
866 QString executable
= myGetFileName(i18n("Select the executable to debug"),
867 m_lastDirectory
, 0, this);
868 if (executable
.isEmpty())
871 debugProgram(executable
, "");
875 void DebuggerMainWnd::slotFileCore()
877 if (m_debugger
->canStart())
879 QString corefile
= myGetFileName(i18n("Select core dump"),
880 m_lastDirectory
, 0, this);
881 if (!corefile
.isEmpty()) {
882 m_debugger
->useCoreFile(corefile
, false);
887 void DebuggerMainWnd::slotFileProgSettings()
889 if (m_debugger
!= 0) {
890 m_debugger
->programSettings(this);
894 void DebuggerMainWnd::slotViewToolbar()
896 if (toolBar()->isVisible())
902 void DebuggerMainWnd::slotViewStatusbar()
904 if (statusBar()->isVisible())
910 void DebuggerMainWnd::slotExecUntil()
916 if (m_filesWindow
->activeLine(file
, lineNo
))
917 m_debugger
->runUntil(file
, lineNo
);
921 void DebuggerMainWnd::slotExecAttach()
924 ProcAttachPS
dlg(this);
925 // seed filter with executable name
926 QFileInfo fi
= m_debugger
->executable();
927 dlg
.filterEdit
->setText(fi
.fileName());
929 ProcAttach
dlg(this);
930 dlg
.setText(m_debugger
->attachedPid());
933 m_debugger
->attachProgram(dlg
.text());
937 void DebuggerMainWnd::slotExecArgs()
939 if (m_debugger
!= 0) {
940 m_debugger
->programArgs(this);
944 void DebuggerMainWnd::slotConfigureKeys()
946 KKeyDialog::configure(actionCollection(), this);
949 #include "dbgmainwnd.moc"