Fixed that the debugger window really moves itself to the foreground.
[kdbg.git] / kdbg / dbgmainwnd.cpp
blob37d76bafffc088d7c85518e18da69c05dc00b0a8
1 // $Id$
3 // Copyright by Johannes Sixt
4 // This file is under GPL, the GNU General Public Licence
6 #include <kapp.h>
7 #include <klocale.h> /* i18n */
8 #include <kmessagebox.h>
9 #include <kconfig.h>
10 #include <kstatusbar.h>
11 #include <kiconloader.h>
12 #include <kstdaccel.h>
13 #include <kstdaction.h>
14 #include <kaction.h>
15 #include <kpopupmenu.h>
16 #include <kfiledialog.h>
17 #include <kprocess.h>
18 #include <kkeydialog.h>
19 #include <kanimwidget.h>
20 #include <kwin.h>
21 #include <qlistbox.h>
22 #include <qfileinfo.h>
23 #include "dbgmainwnd.h"
24 #include "debugger.h"
25 #include "commandids.h"
26 #include "winstack.h"
27 #include "brkpt.h"
28 #include "threadlist.h"
29 #include "memwindow.h"
30 #include "ttywnd.h"
31 #include "procattach.h"
32 #include "dbgdriver.h"
33 #include "mydebug.h"
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
39 DebuggerMainWnd::DebuggerMainWnd(const char* name) :
40 KDockMainWindow(0, name),
41 DebuggerMainWndBase()
43 QPixmap p;
45 KDockWidget* dw0 = createDockWidget("Source", p, 0, i18n("Source"));
46 m_filesWindow = new WinStack(dw0, "files");
47 dw0->setWidget(m_filesWindow);
48 dw0->setDockSite(KDockWidget::DockCorner);
49 dw0->setEnableDocking(KDockWidget::DockNone);
50 setView(dw0);
51 setMainDockWidget(dw0);
53 KDockWidget* dw1 = createDockWidget("Stack", p, 0, i18n("Stack"));
54 m_btWindow = new QListBox(dw1, "backtrace");
55 dw1->setWidget(m_btWindow);
56 KDockWidget* dw2 = createDockWidget("Locals", p, 0, i18n("Locals"));
57 m_localVariables = new ExprWnd(dw2, "locals");
58 dw2->setWidget(m_localVariables);
59 KDockWidget* dw3 = createDockWidget("Watches", p, 0, i18n("Watches"));
60 m_watches = new WatchWindow(dw3, "watches");
61 dw3->setWidget(m_watches);
62 KDockWidget* dw4 = createDockWidget("Registers", p, 0, i18n("Registers"));
63 m_registers = new RegisterView(dw4, "registers");
64 dw4->setWidget(m_registers);
65 KDockWidget* dw5 = createDockWidget("Breakpoints", p, 0, i18n("Breakpoints"));
66 m_bpTable = new BreakpointTable(dw5, "breakpoints");
67 dw5->setWidget(m_bpTable);
68 KDockWidget* dw6 = createDockWidget("Output", p, 0, i18n("Output"));
69 m_ttyWindow = new TTYWindow(dw6, "output");
70 dw6->setWidget(m_ttyWindow);
71 KDockWidget* dw7 = createDockWidget("Threads", p, 0, i18n("Threads"));
72 m_threads = new ThreadList(dw7, "threads");
73 dw7->setWidget(m_threads);
74 KDockWidget* dw8 = createDockWidget("Memory", p, 0, i18n("Memory"));
75 m_memoryWindow = new MemoryWindow(dw8, "memory");
76 dw8->setWidget(m_memoryWindow);
78 setupDebugger(this, m_localVariables, m_watches->watchVariables(), m_btWindow);
79 m_bpTable->setDebugger(m_debugger);
80 m_memoryWindow->setDebugger(m_debugger);
82 initKAction();
83 initToolbar(); // kind of obsolete?
85 connect(m_watches, SIGNAL(addWatch()), SLOT(slotAddWatch()));
86 connect(m_watches, SIGNAL(deleteWatch()), m_debugger, SLOT(slotDeleteWatch()));
88 KAction* windowMenu = actionCollection()->action("window");
89 m_filesWindow->setWindowMenu(static_cast<KActionMenu*>(windowMenu)->popupMenu());
90 connect(&m_filesWindow->m_findDlg, SIGNAL(closed()), SLOT(updateUI()));
91 connect(m_filesWindow, SIGNAL(newFileLoaded()),
92 SLOT(slotNewFileLoaded()));
93 connect(m_filesWindow, SIGNAL(toggleBreak(const QString&,int,const DbgAddr&,bool)),
94 this, SLOT(slotToggleBreak(const QString&,int,const DbgAddr&,bool)));
95 connect(m_filesWindow, SIGNAL(enadisBreak(const QString&,int,const DbgAddr&)),
96 this, SLOT(slotEnaDisBreak(const QString&,int,const DbgAddr&)));
97 connect(m_debugger, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)),
98 m_filesWindow, SLOT(activate(const QString&,int,const DbgAddr&)));
99 connect(m_debugger, SIGNAL(executableUpdated()),
100 m_filesWindow, SLOT(reloadAllFiles()));
101 connect(m_debugger, SIGNAL(updatePC(const QString&,int,const DbgAddr&,int)),
102 m_filesWindow, SLOT(updatePC(const QString&,int,const DbgAddr&,int)));
103 // value popup communication
104 connect(m_filesWindow, SIGNAL(initiateValuePopup(const QString&)),
105 m_debugger, SLOT(slotValuePopup(const QString&)));
106 connect(m_debugger, SIGNAL(valuePopup(const QString&)),
107 m_filesWindow, SLOT(slotShowValueTip(const QString&)));
108 // disassembling
109 connect(m_filesWindow, SIGNAL(disassemble(const QString&, int)),
110 m_debugger, SLOT(slotDisassemble(const QString&, int)));
111 connect(m_debugger, SIGNAL(disassembled(const QString&,int,const QList<DisassembledCode>&)),
112 m_filesWindow, SLOT(slotDisassembled(const QString&,int,const QList<DisassembledCode>&)));
113 connect(m_filesWindow, SIGNAL(moveProgramCounter(const QString&,int,const DbgAddr&)),
114 m_debugger, SLOT(setProgramCounter(const QString&,int,const DbgAddr&)));
115 // program stopped
116 connect(m_debugger, SIGNAL(programStopped()), SLOT(slotProgramStopped()));
117 connect(&m_backTimer, SIGNAL(timeout()), SLOT(slotBackTimer()));
118 // tab width
119 connect(this, SIGNAL(setTabWidth(int)), m_filesWindow, SIGNAL(setTabWidth(int)));
121 // Establish communication when right clicked on file window.
122 connect(m_filesWindow, SIGNAL(filesRightClick(const QPoint &)),
123 SLOT(slotFileWndMenu(const QPoint &)));
125 // Connection when right clicked on file window before any file is
126 // loaded.
127 connect(m_filesWindow, SIGNAL(clickedRight(const QPoint &)),
128 SLOT(slotFileWndEmptyMenu(const QPoint &)));
130 // file/line updates
131 connect(m_filesWindow, SIGNAL(fileChanged()), SLOT(slotFileChanged()));
132 connect(m_filesWindow, SIGNAL(lineChanged()), SLOT(slotLineChanged()));
134 // connect breakpoint table
135 connect(m_bpTable, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)),
136 m_filesWindow, SLOT(activate(const QString&,int,const DbgAddr&)));
137 connect(m_debugger, SIGNAL(updateUI()), m_bpTable, SLOT(updateUI()));
138 connect(m_debugger, SIGNAL(breakpointsChanged()), m_bpTable, SLOT(updateBreakList()));
139 connect(m_debugger, SIGNAL(breakpointsChanged()), m_bpTable, SLOT(updateUI()));
141 connect(m_debugger, SIGNAL(registersChanged(QList<RegisterInfo>&)),
142 m_registers, SLOT(updateRegisters(QList<RegisterInfo>&)));
144 connect(m_debugger, SIGNAL(memoryDumpChanged(const QString&, QList<MemoryDump>&)),
145 m_memoryWindow, SLOT(slotNewMemoryDump(const QString&, QList<MemoryDump>&)));
146 connect(m_debugger, SIGNAL(saveProgramSpecific(KConfigBase*)),
147 m_memoryWindow, SLOT(saveProgramSpecific(KConfigBase*)));
148 connect(m_debugger, SIGNAL(restoreProgramSpecific(KConfigBase*)),
149 m_memoryWindow, SLOT(restoreProgramSpecific(KConfigBase*)));
151 // thread window
152 connect(m_debugger, SIGNAL(threadsChanged(QList<ThreadInfo>&)),
153 m_threads, SLOT(updateThreads(QList<ThreadInfo>&)));
154 connect(m_threads, SIGNAL(setThread(int)),
155 m_debugger, SLOT(setThread(int)));
157 // view menu changes when docking state changes
158 connect(dockManager, SIGNAL(change()), SLOT(updateUI()));
160 // popup menu of the local variables window
161 connect(m_localVariables, SIGNAL(rightPressed(int, const QPoint&)),
162 this, SLOT(slotLocalsPopup(int, const QPoint&)));
164 restoreSettings(kapp->config());
166 updateUI();
167 m_bpTable->updateUI();
168 slotFileChanged();
171 DebuggerMainWnd::~DebuggerMainWnd()
173 saveSettings(kapp->config());
174 // must delete m_debugger early since it references our windows
175 delete m_debugger;
176 m_debugger = 0;
178 delete m_memoryWindow;
179 delete m_threads;
180 delete m_ttyWindow;
181 delete m_bpTable;
182 delete m_registers;
183 delete m_watches;
184 delete m_localVariables;
185 delete m_btWindow;
186 delete m_filesWindow;
189 void DebuggerMainWnd::initKAction()
191 // file menu
192 KAction* open = KStdAction::open(this, SLOT(slotFileOpen()),
193 actionCollection());
194 open->setText(i18n("&Open Source..."));
195 (void)new KAction(i18n("&Reload Source"), "reload", 0, m_filesWindow,
196 SLOT(slotFileReload()), actionCollection(),
197 "file_reload");
198 (void)new KAction(i18n("&Executable..."), "execopen", 0, this,
199 SLOT(slotFileExe()), actionCollection(),
200 "file_executable");
201 m_recentExecAction = new KRecentFilesAction(i18n("Recent E&xecutables"), 0,
202 this, SLOT(slotRecentExec(const KURL&)),
203 actionCollection(), "file_executable_recent");
204 (void)new KAction(i18n("&Core dump..."), 0, this, SLOT(slotFileCore()),
205 actionCollection(), "file_core_dump");
206 KStdAction::quit(this, SLOT(slotFileQuit()), actionCollection());
208 // settings menu
209 (void)new KAction(i18n("This &Program..."), 0, this,
210 SLOT(slotFileProgSettings()), actionCollection(),
211 "settings_program");
212 (void)new KAction(i18n("&Global Options..."), 0, this,
213 SLOT(slotFileGlobalSettings()), actionCollection(),
214 "settings_global");
215 KStdAction::keyBindings(this, SLOT(slotConfigureKeys()), actionCollection());
216 KStdAction::showToolbar(this, SLOT(slotViewToolbar()), actionCollection());
217 KStdAction::showStatusbar(this, SLOT(slotViewStatusbar()), actionCollection());
219 // view menu
220 (void)new KToggleAction(i18n("&Find"), "find", 0, m_filesWindow,
221 SLOT(slotViewFind()), actionCollection(),
222 "view_find");
223 i18n("Source &code");
224 struct { QString text; QWidget* w; QString id; } dw[] = {
225 { i18n("Stac&k"), m_btWindow, "view_stack"},
226 { i18n("&Locals"), m_localVariables, "view_locals"},
227 { i18n("&Watched expressions"), m_watches, "view_watched_expressions"},
228 { i18n("&Registers"), m_registers, "view_registers"},
229 { i18n("&Breakpoints"), m_bpTable, "view_breakpoints"},
230 { i18n("T&hreads"), m_threads, "view_threads"},
231 { i18n("&Output"), m_ttyWindow, "view_output"},
232 { i18n("&Memory"), m_memoryWindow, "view_memory"}
234 for (unsigned i = 0; i < sizeof(dw)/sizeof(dw[0]); i++) {
235 KDockWidget* d = dockParent(dw[i].w);
236 (void)new KToggleAction(dw[i].text, 0, d, SLOT(changeHideShowState()),
237 actionCollection(), dw[i].id);
241 // execution menu
242 KAction* a = new KAction(i18n("&Run"), "pgmrun", Key_F5, m_debugger,
243 SLOT(programRun()), actionCollection(), "exec_run");
244 connect(a, SIGNAL(activated()), this, SLOT(intoBackground()));
245 a = new KAction(i18n("Step &into"), "pgmstep", Key_F8, m_debugger,
246 SLOT(programStep()), actionCollection(),
247 "exec_step_into");
248 connect(a, SIGNAL(activated()), this, SLOT(intoBackground()));
249 a = new KAction(i18n("Step &over"), "pgmnext", Key_F10, m_debugger,
250 SLOT(programNext()), actionCollection(),
251 "exec_step_over");
252 connect(a, SIGNAL(activated()), this, SLOT(intoBackground()));
253 a = new KAction(i18n("Step o&ut"), "pgmfinish", Key_F6, m_debugger,
254 SLOT(programFinish()), actionCollection(),
255 "exec_step_out");
256 connect(a, SIGNAL(activated()), this, SLOT(intoBackground()));
257 a = new KAction(i18n("Run to &cursor"), Key_F7, this,
258 SLOT(slotExecUntil()), actionCollection(),
259 "exec_run_to_cursor");
260 connect(a, SIGNAL(activated()), this, SLOT(intoBackground()));
261 a = new KAction(i18n("Step i&nto by instruction"), "pgmstepi",
262 SHIFT+Key_F8, m_debugger, SLOT(programStepi()),
263 actionCollection(), "exec_step_into_by_insn");
264 connect(a, SIGNAL(activated()), this, SLOT(intoBackground()));
265 a = new KAction(i18n("Step o&ver by instruction"), "pgmnexti",
266 SHIFT+Key_F10, m_debugger, SLOT(programNexti()),
267 actionCollection(), "exec_step_over_by_insn");
268 connect(a, SIGNAL(activated()), this, SLOT(intoBackground()));
269 (void)new KAction(i18n("&Program counter to current line"), 0,
270 m_filesWindow, SLOT(slotMoveProgramCounter()),
271 actionCollection(), "exec_movepc");
272 (void)new KAction(i18n("&Break"), 0, m_debugger,
273 SLOT(programBreak()), actionCollection(),
274 "exec_break");
275 (void)new KAction(i18n("&Kill"), 0, m_debugger,
276 SLOT(programKill()), actionCollection(),
277 "exec_kill");
278 (void)new KAction(i18n("Re&start"), 0, m_debugger,
279 SLOT(programRunAgain()), actionCollection(),
280 "exec_restart");
281 (void)new KAction(i18n("A&ttach..."), 0, this,
282 SLOT(slotExecAttach()), actionCollection(),
283 "exec_attach");
284 (void)new KAction(i18n("&Arguments..."), 0, this,
285 SLOT(slotExecArgs()), actionCollection(),
286 "exec_arguments");
288 // breakpoint menu
289 (void)new KAction(i18n("Set/Clear &breakpoint"), "brkpt", Key_F9,
290 m_filesWindow, SLOT(slotBrkptSet()), actionCollection(),
291 "breakpoint_set");
292 (void)new KAction(i18n("Set &temporary breakpoint"), SHIFT+Key_F9,
293 m_filesWindow, SLOT(slotBrkptSetTemp()), actionCollection(),
294 "breakpoint_set_temporary");
295 (void)new KAction(i18n("&Enable/Disable breakpoint"), CTRL+Key_F9,
296 m_filesWindow, SLOT(slotBrkptEnable()), actionCollection(),
297 "breakpoint_enable");
299 // only in popup menus
300 (void)new KAction(i18n("Watch Expression"), 0, this,
301 SLOT(slotLocalsToWatch()), actionCollection(),
302 "watch_expression");
303 (void)new KAction(i18n("Edit Value"), Key_F2, this,
304 SLOT(slotEditValue()), actionCollection(),
305 "edit_value");
307 (void)new KActionMenu(i18n("&Window"), actionCollection(), "window");
309 // all actions force an UI update
310 QValueList<KAction*> actions = actionCollection()->actions();
311 QValueList<KAction*>::Iterator it = actions.begin();
312 for (; it != actions.end(); ++it) {
313 connect(*it, SIGNAL(activated()), this, SLOT(updateUI()));
316 createGUI("kdbgui.rc");
319 void DebuggerMainWnd::initToolbar()
321 KToolBar* toolbar = toolBar("mainToolBar");
322 toolbar->setBarPos(KToolBar::Top);
323 //moveToolBar(toolbar);
325 toolbar->insertAnimatedWidget(ID_STATUS_BUSY,
326 actionCollection()->action("exec_break"), SLOT(activate()),
327 "pulse", -1);
328 toolbar->alignItemRight(ID_STATUS_BUSY, true);
329 m_animRunning = false;
331 KStatusBar* statusbar = statusBar();
332 statusbar->insertItem(m_statusActive, ID_STATUS_ACTIVE);
333 m_lastActiveStatusText = m_statusActive;
334 statusbar->insertItem(i18n("Line 00000"), ID_STATUS_LINENO);
335 statusbar->insertItem("", ID_STATUS_MSG); /* message pane */
337 // reserve some translations
338 i18n("Restart");
339 i18n("Core dump");
343 * We must override KTMainWindow's handling of close events since we have
344 * only one toplevel window, which lives on the stack (which KTMainWindow
345 * can't live with :-( )
347 void DebuggerMainWnd::closeEvent(QCloseEvent* e)
349 clearWFlags(WDestructiveClose);
351 if (m_debugger != 0) {
352 m_debugger->shutdown();
355 e->accept();
356 kapp->quit();
360 // instance properties
361 void DebuggerMainWnd::saveProperties(KConfig* config)
363 // session management
364 QString executable = "";
365 if (m_debugger != 0) {
366 executable = m_debugger->executable();
368 config->writeEntry("executable", executable);
371 void DebuggerMainWnd::readProperties(KConfig* config)
373 // session management
374 QString execName = config->readEntry("executable");
376 TRACE("readProperties: executable=" + execName);
377 if (!execName.isEmpty()) {
378 debugProgram(execName, "");
382 const char WindowGroup[] = "Windows";
383 const char RecentExecutables[] = "RecentExecutables";
385 void DebuggerMainWnd::saveSettings(KConfig* config)
387 KConfigGroupSaver g(config, WindowGroup);
389 writeDockConfig(config);
390 fixDockConfig(config, false); // downgrade
392 m_recentExecAction->saveEntries(config, RecentExecutables);
394 DebuggerMainWndBase::saveSettings(config);
397 void DebuggerMainWnd::restoreSettings(KConfig* config)
399 KConfigGroupSaver g(config, WindowGroup);
401 fixDockConfig(config, true); // upgrade
402 readDockConfig(config);
404 m_recentExecAction->loadEntries(config, RecentExecutables);
406 DebuggerMainWndBase::restoreSettings(config);
408 emit setTabWidth(m_tabWidth);
411 void DebuggerMainWnd::updateUI()
413 KToggleAction* viewFind =
414 static_cast<KToggleAction*>(actionCollection()->action("view_find"));
415 viewFind->setChecked(m_filesWindow->m_findDlg.isVisible());
416 viewFind->setEnabled(m_filesWindow->hasWindows());
417 actionCollection()->action("breakpoint_set")->setEnabled(m_debugger->canChangeBreakpoints());
418 actionCollection()->action("breakpoint_set_temporary")->setEnabled(m_debugger->canChangeBreakpoints());
419 actionCollection()->action("breakpoint_enable")->setEnabled(m_debugger->canChangeBreakpoints());
420 dockUpdateHelper("view_breakpoints", m_bpTable);
421 dockUpdateHelper("view_stack", m_btWindow);
422 dockUpdateHelper("view_locals", m_localVariables);
423 dockUpdateHelper("view_watched_expressions", m_watches);
424 dockUpdateHelper("view_registers", m_registers);
425 dockUpdateHelper("view_threads", m_threads);
426 dockUpdateHelper("view_memory", m_memoryWindow);
427 dockUpdateHelper("view_output", m_ttyWindow);
429 // AB: maybe in mainwndbase.cpp?
430 actionCollection()->action("file_executable")->setEnabled(m_debugger->isIdle());
431 actionCollection()->action("settings_program")->setEnabled(m_debugger->haveExecutable());
432 actionCollection()->action("file_core_dump")->setEnabled(m_debugger->canStart());
433 actionCollection()->action("exec_step_into")->setEnabled(m_debugger->canSingleStep());
434 actionCollection()->action("exec_step_into_by_insn")->setEnabled(m_debugger->canSingleStep());
435 actionCollection()->action("exec_step_over")->setEnabled(m_debugger->canSingleStep());
436 actionCollection()->action("exec_step_over_by_insn")->setEnabled(m_debugger->canSingleStep());
437 actionCollection()->action("exec_step_out")->setEnabled(m_debugger->canSingleStep());
438 actionCollection()->action("exec_run_to_cursor")->setEnabled(m_debugger->canSingleStep());
439 actionCollection()->action("exec_movepc")->setEnabled(m_debugger->canSingleStep());
440 actionCollection()->action("exec_restart")->setEnabled(m_debugger->canSingleStep());
441 actionCollection()->action("exec_attach")->setEnabled(m_debugger->isReady());
442 actionCollection()->action("exec_run")->setEnabled(m_debugger->canStart() || m_debugger->canSingleStep());
443 actionCollection()->action("exec_kill")->setEnabled(m_debugger->haveExecutable() && m_debugger->isProgramActive());
444 actionCollection()->action("exec_break")->setEnabled(m_debugger->isProgramRunning());
445 actionCollection()->action("exec_arguments")->setEnabled(m_debugger->haveExecutable());
446 actionCollection()->action("edit_value")->setEnabled(m_debugger->canSingleStep());
448 // animation
449 KAnimWidget* w = toolBar("mainToolBar")->animatedWidget(ID_STATUS_BUSY);
450 if (m_debugger->isIdle()) {
451 if (m_animRunning) {
452 w->stop();
453 m_animRunning = false;
455 } else {
456 if (!m_animRunning) {
457 w->start();
458 m_animRunning = true;
462 // update statusbar
463 QString newStatus;
464 if (m_debugger->isProgramActive())
465 newStatus = m_statusActive;
466 if (newStatus != m_lastActiveStatusText) {
467 statusBar()->changeItem(newStatus, ID_STATUS_ACTIVE);
468 m_lastActiveStatusText = newStatus;
470 // line number is updated in slotLineChanged
473 void DebuggerMainWnd::dockUpdateHelper(QString action, QWidget* w)
475 KToggleAction* item =
476 static_cast<KToggleAction*>(actionCollection()->action(action));
477 bool canChange = canChangeDockVisibility(w);
478 item->setEnabled(canChange);
479 item->setChecked(canChange && isDockVisible(w));
482 void DebuggerMainWnd::updateLineItems()
484 m_filesWindow->updateLineItems(m_debugger);
487 void DebuggerMainWnd::slotAddWatch()
489 if (m_debugger != 0) {
490 QString t = m_watches->watchText();
491 m_debugger->addWatch(t);
495 void DebuggerMainWnd::slotFileChanged()
497 // set caption
498 QString caption;
500 if (m_debugger->haveExecutable()) {
501 // basename part of executable
502 QString executable = m_debugger->executable();
503 const char* execBase = executable.data();
504 int lastSlash = executable.findRev('/');
505 if (lastSlash >= 0)
506 execBase += lastSlash + 1;
507 caption += execBase;
509 QString file;
510 int line;
511 bool anyWindows = m_filesWindow->activeLine(file, line);
512 updateLineStatus(anyWindows ? line : -1);
513 if (anyWindows) {
514 caption += " (";
515 caption += file;
516 caption += ")";
518 setCaption(caption);
521 void DebuggerMainWnd::slotLineChanged()
523 QString file;
524 int line;
525 bool anyWindows = m_filesWindow->activeLine(file, line);
526 updateLineStatus(anyWindows ? line : -1);
529 void DebuggerMainWnd::slotNewFileLoaded()
531 // updates program counter in the new file
532 if (m_debugger != 0)
533 m_filesWindow->updateLineItems(m_debugger);
536 void DebuggerMainWnd::updateLineStatus(int lineNo)
538 if (lineNo < 0) {
539 statusBar()->changeItem("", ID_STATUS_LINENO);
540 } else {
541 QString strLine;
542 strLine.sprintf(i18n("Line %d"), lineNo + 1);
543 statusBar()->changeItem(strLine, ID_STATUS_LINENO);
547 KDockWidget* DebuggerMainWnd::dockParent(QWidget* w)
549 while ((w = w->parentWidget()) != 0) {
550 if (w->isA("KDockWidget"))
551 return static_cast<KDockWidget*>(w);
553 return 0;
556 bool DebuggerMainWnd::isDockVisible(QWidget* w)
558 KDockWidget* d = dockParent(w);
559 return d != 0 && d->mayBeHide();
562 bool DebuggerMainWnd::canChangeDockVisibility(QWidget* w)
564 KDockWidget* d = dockParent(w);
565 return d != 0 && (d->mayBeHide() || d->mayBeShow());
568 // upgrades the entries from version 0.0.4 to 0.0.5 and back
569 void DebuggerMainWnd::fixDockConfig(KConfig* c, bool upgrade)
571 static const char dockGroup[] = "dock_setting_default";
572 if (!c->hasGroup(dockGroup))
573 return;
575 static const char oldVersion[] = "0.0.4";
576 static const char newVersion[] = "0.0.5";
577 const char* from = upgrade ? oldVersion : newVersion;
578 const char* to = upgrade ? newVersion : oldVersion;
579 QMap<QString,QString> e = c->entryMap(dockGroup);
580 if (e["Version"] != from)
581 return;
583 KConfigGroupSaver g(c, dockGroup);
584 c->writeEntry("Version", to);
585 TRACE(upgrade ? "upgrading dockconfig" : "downgrading dockconfig");
587 // turn all orientation entries from 0 to 1 and from 1 to 0
588 QMap<QString,QString>::Iterator i;
589 for (i = e.begin(); i != e.end(); ++i)
591 if (i.key().right(12) == ":orientation") {
592 TRACE("upgrading " + i.key() + " old value: " + *i);
593 int orientation = c->readNumEntry(i.key(), -1);
594 if (orientation >= 0) { // paranoia
595 c->writeEntry(i.key(), 1 - orientation);
601 TTYWindow* DebuggerMainWnd::ttyWindow()
603 return m_ttyWindow;
606 bool DebuggerMainWnd::debugProgram(const QString& exe, QCString lang)
608 // check the file name
609 QFileInfo fi(exe);
611 bool success = fi.isFile();
612 if (!success)
614 QString msg = i18n("`%1' is not a file or does not exist");
615 KMessageBox::sorry(this, msg.arg(exe));
617 else
619 success = DebuggerMainWndBase::debugProgram(fi.absFilePath(), lang, this);
622 if (success)
624 m_recentExecAction->addURL(KURL(fi.absFilePath()));
626 // keep the directory
627 m_lastDirectory = fi.dirPath(true);
628 m_filesWindow->setExtraDirectory(m_lastDirectory);
630 else
632 m_recentExecAction->removeURL(KURL(fi.absFilePath()));
635 return true;
638 void DebuggerMainWnd::slotNewStatusMsg()
640 newStatusMsg(statusBar());
643 void DebuggerMainWnd::slotFileGlobalSettings()
645 int oldTabWidth = m_tabWidth;
647 doGlobalOptions(this);
649 if (m_tabWidth != oldTabWidth) {
650 emit setTabWidth(m_tabWidth);
654 void DebuggerMainWnd::slotDebuggerStarting()
656 DebuggerMainWndBase::slotDebuggerStarting();
659 void DebuggerMainWnd::slotToggleBreak(const QString& fileName, int lineNo,
660 const DbgAddr& address, bool temp)
662 // lineNo is zero-based
663 if (m_debugger != 0) {
664 m_debugger->setBreakpoint(fileName, lineNo, address, temp);
668 void DebuggerMainWnd::slotEnaDisBreak(const QString& fileName, int lineNo,
669 const DbgAddr& address)
671 // lineNo is zero-based
672 if (m_debugger != 0) {
673 m_debugger->enableDisableBreakpoint(fileName, lineNo, address);
677 QString DebuggerMainWnd::createOutputWindow()
679 QString tty = DebuggerMainWndBase::createOutputWindow();
680 if (!tty.isEmpty()) {
681 connect(m_outputTermProc, SIGNAL(processExited(KProcess*)),
682 SLOT(slotTermEmuExited()));
684 return tty;
687 void DebuggerMainWnd::slotTermEmuExited()
689 shutdownTermWindow();
692 void DebuggerMainWnd::slotProgramStopped()
694 // when the program stopped, move the window to the foreground
695 if (m_popForeground) {
696 // unfortunately, this requires quite some force to work :-(
697 KWin::raiseWindow(winId());
698 KWin::forceActiveWindow(winId());
700 m_backTimer.stop();
703 void DebuggerMainWnd::intoBackground()
705 if (m_popForeground) {
706 m_backTimer.start(m_backTimeout, true); /* single-shot */
710 void DebuggerMainWnd::slotBackTimer()
712 lower();
715 void DebuggerMainWnd::slotRecentExec(const KURL& url)
717 QString exe = url.path();
718 debugProgram(exe, "");
721 QString DebuggerMainWnd::makeSourceFilter()
723 QString f;
724 f = m_sourceFilter + " " + m_headerFilter + i18n("|All source files\n");
725 f += m_sourceFilter + i18n("|Source files\n");
726 f += m_headerFilter + i18n("|Header files\n");
727 f += i18n("*|All files");
728 return f;
732 * Pop up the context menu in the locals window
734 void DebuggerMainWnd::slotLocalsPopup(int, const QPoint& pt)
736 QPopupMenu* popup =
737 static_cast<QPopupMenu*>(factory()->container("popup_locals", this));
738 if (popup == 0) {
739 return;
741 if (popup->isVisible()) {
742 popup->hide();
743 } else {
744 popup->popup(m_localVariables->mapToGlobal(pt));
749 * Copies the currently selected item to the watch window.
751 void DebuggerMainWnd::slotLocalsToWatch()
753 int idx = m_localVariables->currentItem();
755 if (idx >= 0 && m_debugger != 0) {
756 QString text = m_localVariables->exprStringAt(idx);
757 m_debugger->addWatch(text);
762 * Starts editing a value in a value display
764 void DebuggerMainWnd::slotEditValue()
766 // does one of the value trees have the focus
767 QWidget* f = kapp->focusWidget();
768 ExprWnd* wnd;
769 if (f == m_localVariables) {
770 wnd = m_localVariables;
771 } else if (f == m_watches->watchVariables()) {
772 wnd = m_watches->watchVariables();
773 } else {
774 return;
777 if (m_localVariables->isEditing() ||
778 m_watches->watchVariables()->isEditing())
780 return; /* don't edit twice */
783 int idx = wnd->currentItem();
784 if (idx >= 0 && m_debugger != 0 && m_debugger->canSingleStep())
786 TRACE("edit value");
787 // determine the text to edit
788 VarTree* expr = static_cast<VarTree*>(wnd->itemAt(idx));
789 QString text = m_debugger->driver()->editableValue(expr);
790 wnd->editValue(idx, text);
794 // Pop up the context menu of the files window (for loaded files)
795 void DebuggerMainWnd::slotFileWndMenu(const QPoint& pos)
797 QPopupMenu* popup =
798 static_cast<QPopupMenu*>(factory()->container("popup_files", this));
799 if (popup == 0) {
800 return;
802 if (popup->isVisible()) {
803 popup->hide();
804 } else {
805 // pos is still in widget coordinates of the sender
806 const QWidget* w = static_cast<const QWidget*>(sender());
807 popup->popup(w->mapToGlobal(pos));
811 // Pop up the context menu of the files window (while no file is loaded)
812 void DebuggerMainWnd::slotFileWndEmptyMenu(const QPoint& pos)
814 QPopupMenu* popup =
815 static_cast<QPopupMenu*>(factory()->container("popup_files_empty", this));
816 if (popup == 0) {
817 return;
819 if (popup->isVisible()) {
820 popup->hide();
821 } else {
822 // pos is still in widget coordinates of the sender
823 const QWidget* w = static_cast<const QWidget*>(sender());
824 popup->popup(w->mapToGlobal(pos));
828 void DebuggerMainWnd::slotFileOpen()
830 QString fileName = myGetFileName(i18n("Open"),
831 m_lastDirectory,
832 makeSourceFilter(), this);
834 if (!fileName.isEmpty())
836 QFileInfo fi(fileName);
837 m_lastDirectory = fi.dirPath();
838 m_filesWindow->setExtraDirectory(m_lastDirectory);
839 m_filesWindow->activateFile(fileName);
843 void DebuggerMainWnd::slotFileQuit()
845 if (m_debugger != 0) {
846 m_debugger->shutdown();
848 kapp->quit();
851 void DebuggerMainWnd::slotFileExe()
853 if (m_debugger->isIdle())
855 // open a new executable
856 QString executable = myGetFileName(i18n("Select the executable to debug"),
857 m_lastDirectory, 0, this);
858 if (executable.isEmpty())
859 return;
861 debugProgram(executable, "");
865 void DebuggerMainWnd::slotFileCore()
867 if (m_debugger->canStart())
869 QString corefile = myGetFileName(i18n("Select core dump"),
870 m_lastDirectory, 0, this);
871 if (!corefile.isEmpty()) {
872 m_debugger->useCoreFile(corefile, false);
877 void DebuggerMainWnd::slotFileProgSettings()
879 if (m_debugger != 0) {
880 m_debugger->programSettings(this);
884 void DebuggerMainWnd::slotViewToolbar()
886 if (toolBar()->isVisible())
887 toolBar()->hide();
888 else
889 toolBar()->show();
892 void DebuggerMainWnd::slotViewStatusbar()
894 if (statusBar()->isVisible())
895 statusBar()->hide();
896 else
897 statusBar()->show();
900 void DebuggerMainWnd::slotExecUntil()
902 if (m_debugger != 0)
904 QString file;
905 int lineNo;
906 if (m_filesWindow->activeLine(file, lineNo))
907 m_debugger->runUntil(file, lineNo);
911 void DebuggerMainWnd::slotExecAttach()
913 #ifdef PS_COMMAND
914 ProcAttachPS dlg(this);
915 #else
916 ProcAttach dlg(this);
917 dlg.setText(m_debugger->attachedPid());
918 #endif
919 if (dlg.exec()) {
920 m_debugger->attachProgram(dlg.text());
924 void DebuggerMainWnd::slotExecArgs()
926 if (m_debugger != 0) {
927 m_debugger->programArgs(this);
931 void DebuggerMainWnd::slotConfigureKeys()
933 KKeyDialog::configure(actionCollection(), this);
936 #include "dbgmainwnd.moc"