Fixed that Run/Continue button was enabled while the program is running.
[kdbg.git] / kdbg / dbgmainwnd.cpp
blob7c42049a8b2e4b8c626f16dd0f06171781e8a45c
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 <qlistbox.h>
21 #include <qfileinfo.h>
22 #include "dbgmainwnd.h"
23 #include "debugger.h"
24 #include "commandids.h"
25 #include "winstack.h"
26 #include "brkpt.h"
27 #include "threadlist.h"
28 #include "memwindow.h"
29 #include "ttywnd.h"
30 #include "procattach.h"
31 #include "dbgdriver.h"
32 #include "mydebug.h"
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
38 DebuggerMainWnd::DebuggerMainWnd(const char* name) :
39 KDockMainWindow(0, name),
40 DebuggerMainWndBase()
42 QPixmap p;
44 KDockWidget* dw0 = createDockWidget("Source", p, 0, i18n("Source"));
45 m_filesWindow = new WinStack(dw0, "files");
46 dw0->setWidget(m_filesWindow);
47 dw0->setDockSite(KDockWidget::DockCorner);
48 dw0->setEnableDocking(KDockWidget::DockNone);
49 setView(dw0);
50 setMainDockWidget(dw0);
52 KDockWidget* dw1 = createDockWidget("Stack", p, 0, i18n("Stack"));
53 m_btWindow = new QListBox(dw1, "backtrace");
54 dw1->setWidget(m_btWindow);
55 KDockWidget* dw2 = createDockWidget("Locals", p, 0, i18n("Locals"));
56 m_localVariables = new ExprWnd(dw2, "locals");
57 dw2->setWidget(m_localVariables);
58 KDockWidget* dw3 = createDockWidget("Watches", p, 0, i18n("Watches"));
59 m_watches = new WatchWindow(dw3, "watches");
60 dw3->setWidget(m_watches);
61 KDockWidget* dw4 = createDockWidget("Registers", p, 0, i18n("Registers"));
62 m_registers = new RegisterView(dw4, "registers");
63 dw4->setWidget(m_registers);
64 KDockWidget* dw5 = createDockWidget("Breakpoints", p, 0, i18n("Breakpoints"));
65 m_bpTable = new BreakpointTable(dw5, "breakpoints");
66 dw5->setWidget(m_bpTable);
67 KDockWidget* dw6 = createDockWidget("Output", p, 0, i18n("Output"));
68 m_ttyWindow = new TTYWindow(dw6, "output");
69 dw6->setWidget(m_ttyWindow);
70 KDockWidget* dw7 = createDockWidget("Threads", p, 0, i18n("Threads"));
71 m_threads = new ThreadList(dw7, "threads");
72 dw7->setWidget(m_threads);
73 KDockWidget* dw8 = createDockWidget("Memory", p, 0, i18n("Memory"));
74 m_memoryWindow = new MemoryWindow(dw8, "memory");
75 dw8->setWidget(m_memoryWindow);
77 setupDebugger(this, m_localVariables, m_watches->watchVariables(), m_btWindow);
78 m_bpTable->setDebugger(m_debugger);
79 m_memoryWindow->setDebugger(m_debugger);
81 initKAction();
82 initToolbar(); // kind of obsolete?
84 connect(m_watches, SIGNAL(addWatch()), SLOT(slotAddWatch()));
85 connect(m_watches, SIGNAL(deleteWatch()), m_debugger, SLOT(slotDeleteWatch()));
87 KAction* windowMenu = actionCollection()->action("window");
88 m_filesWindow->setWindowMenu(static_cast<KActionMenu*>(windowMenu)->popupMenu());
89 connect(&m_filesWindow->m_findDlg, SIGNAL(closed()), SLOT(updateUI()));
90 connect(m_filesWindow, SIGNAL(newFileLoaded()),
91 SLOT(slotNewFileLoaded()));
92 connect(m_filesWindow, SIGNAL(toggleBreak(const QString&,int,const DbgAddr&,bool)),
93 this, SLOT(slotToggleBreak(const QString&,int,const DbgAddr&,bool)));
94 connect(m_filesWindow, SIGNAL(enadisBreak(const QString&,int,const DbgAddr&)),
95 this, SLOT(slotEnaDisBreak(const QString&,int,const DbgAddr&)));
96 connect(m_debugger, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)),
97 m_filesWindow, SLOT(activate(const QString&,int,const DbgAddr&)));
98 connect(m_debugger, SIGNAL(executableUpdated()),
99 m_filesWindow, SLOT(reloadAllFiles()));
100 connect(m_debugger, SIGNAL(updatePC(const QString&,int,const DbgAddr&,int)),
101 m_filesWindow, SLOT(updatePC(const QString&,int,const DbgAddr&,int)));
102 // value popup communication
103 connect(m_filesWindow, SIGNAL(initiateValuePopup(const QString&)),
104 m_debugger, SLOT(slotValuePopup(const QString&)));
105 connect(m_debugger, SIGNAL(valuePopup(const QString&)),
106 m_filesWindow, SLOT(slotShowValueTip(const QString&)));
107 // disassembling
108 connect(m_filesWindow, SIGNAL(disassemble(const QString&, int)),
109 m_debugger, SLOT(slotDisassemble(const QString&, int)));
110 connect(m_debugger, SIGNAL(disassembled(const QString&,int,const QList<DisassembledCode>&)),
111 m_filesWindow, SLOT(slotDisassembled(const QString&,int,const QList<DisassembledCode>&)));
112 connect(m_filesWindow, SIGNAL(moveProgramCounter(const QString&,int,const DbgAddr&)),
113 m_debugger, SLOT(setProgramCounter(const QString&,int,const DbgAddr&)));
114 // program stopped
115 connect(m_debugger, SIGNAL(programStopped()), SLOT(slotProgramStopped()));
116 connect(&m_backTimer, SIGNAL(timeout()), SLOT(slotBackTimer()));
117 // tab width
118 connect(this, SIGNAL(setTabWidth(int)), m_filesWindow, SIGNAL(setTabWidth(int)));
120 // Establish communication when right clicked on file window.
121 connect(m_filesWindow, SIGNAL(filesRightClick(const QPoint &)),
122 SLOT(slotFileWndMenu(const QPoint &)));
124 // Connection when right clicked on file window before any file is
125 // loaded.
126 connect(m_filesWindow, SIGNAL(clickedRight(const QPoint &)),
127 SLOT(slotFileWndEmptyMenu(const QPoint &)));
129 // file/line updates
130 connect(m_filesWindow, SIGNAL(fileChanged()), SLOT(slotFileChanged()));
131 connect(m_filesWindow, SIGNAL(lineChanged()), SLOT(slotLineChanged()));
133 // connect breakpoint table
134 connect(m_bpTable, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)),
135 m_filesWindow, SLOT(activate(const QString&,int,const DbgAddr&)));
136 connect(m_debugger, SIGNAL(updateUI()), m_bpTable, SLOT(updateUI()));
137 connect(m_debugger, SIGNAL(breakpointsChanged()), m_bpTable, SLOT(updateBreakList()));
138 connect(m_debugger, SIGNAL(breakpointsChanged()), m_bpTable, SLOT(updateUI()));
140 connect(m_debugger, SIGNAL(registersChanged(QList<RegisterInfo>&)),
141 m_registers, SLOT(updateRegisters(QList<RegisterInfo>&)));
143 connect(m_debugger, SIGNAL(memoryDumpChanged(const QString&, QList<MemoryDump>&)),
144 m_memoryWindow, SLOT(slotNewMemoryDump(const QString&, QList<MemoryDump>&)));
145 connect(m_debugger, SIGNAL(saveProgramSpecific(KConfigBase*)),
146 m_memoryWindow, SLOT(saveProgramSpecific(KConfigBase*)));
147 connect(m_debugger, SIGNAL(restoreProgramSpecific(KConfigBase*)),
148 m_memoryWindow, SLOT(restoreProgramSpecific(KConfigBase*)));
150 // thread window
151 connect(m_debugger, SIGNAL(threadsChanged(QList<ThreadInfo>&)),
152 m_threads, SLOT(updateThreads(QList<ThreadInfo>&)));
153 connect(m_threads, SIGNAL(setThread(int)),
154 m_debugger, SLOT(setThread(int)));
156 // view menu changes when docking state changes
157 connect(dockManager, SIGNAL(change()), SLOT(updateUI()));
159 // popup menu of the local variables window
160 connect(m_localVariables, SIGNAL(rightPressed(int, const QPoint&)),
161 this, SLOT(slotLocalsPopup(int, const QPoint&)));
163 restoreSettings(kapp->config());
165 updateUI();
166 m_bpTable->updateUI();
167 slotFileChanged();
170 DebuggerMainWnd::~DebuggerMainWnd()
172 saveSettings(kapp->config());
173 // must delete m_debugger early since it references our windows
174 delete m_debugger;
175 m_debugger = 0;
177 delete m_memoryWindow;
178 delete m_threads;
179 delete m_ttyWindow;
180 delete m_bpTable;
181 delete m_registers;
182 delete m_watches;
183 delete m_localVariables;
184 delete m_btWindow;
185 delete m_filesWindow;
188 void DebuggerMainWnd::initKAction()
190 // file menu
191 KAction* open = KStdAction::open(this, SLOT(slotFileOpen()),
192 actionCollection());
193 open->setText(i18n("&Open Source..."));
194 (void)new KAction(i18n("&Reload Source"), "reload", 0, m_filesWindow,
195 SLOT(slotFileReload()), actionCollection(),
196 "file_reload");
197 (void)new KAction(i18n("&Executable..."), "execopen", 0, this,
198 SLOT(slotFileExe()), actionCollection(),
199 "file_executable");
200 m_recentExecAction = new KRecentFilesAction(i18n("Recent E&xecutables"), 0,
201 this, SLOT(slotRecentExec(const KURL&)),
202 actionCollection(), "file_executable_recent");
203 (void)new KAction(i18n("&Core dump..."), 0, this, SLOT(slotFileCore()),
204 actionCollection(), "file_core_dump");
205 KStdAction::quit(this, SLOT(slotFileQuit()), actionCollection());
207 // settings menu
208 (void)new KAction(i18n("This &Program..."), 0, this,
209 SLOT(slotFileProgSettings()), actionCollection(),
210 "settings_program");
211 (void)new KAction(i18n("&Global Options..."), 0, this,
212 SLOT(slotFileGlobalSettings()), actionCollection(),
213 "settings_global");
214 KStdAction::keyBindings(this, SLOT(slotConfigureKeys()), actionCollection());
215 KStdAction::showToolbar(this, SLOT(slotViewToolbar()), actionCollection());
216 KStdAction::showStatusbar(this, SLOT(slotViewStatusbar()), actionCollection());
218 // view menu
219 (void)new KToggleAction(i18n("&Find"), "find", 0, m_filesWindow,
220 SLOT(slotViewFind()), actionCollection(),
221 "view_find");
222 i18n("Source &code");
223 struct { QString text; QWidget* w; QString id; } dw[] = {
224 { i18n("Stac&k"), m_btWindow, "view_stack"},
225 { i18n("&Locals"), m_localVariables, "view_locals"},
226 { i18n("&Watched expressions"), m_watches, "view_watched_expressions"},
227 { i18n("&Registers"), m_registers, "view_registers"},
228 { i18n("&Breakpoints"), m_bpTable, "view_breakpoints"},
229 { i18n("T&hreads"), m_threads, "view_threads"},
230 { i18n("&Output"), m_ttyWindow, "view_output"},
231 { i18n("&Memory"), m_memoryWindow, "view_memory"}
233 for (unsigned i = 0; i < sizeof(dw)/sizeof(dw[0]); i++) {
234 KDockWidget* d = dockParent(dw[i].w);
235 (void)new KToggleAction(dw[i].text, 0, d, SLOT(changeHideShowState()),
236 actionCollection(), dw[i].id);
240 // execution menu
241 KAction* a = new KAction(i18n("&Run"), "pgmrun", Key_F5, m_debugger,
242 SLOT(programRun()), actionCollection(), "exec_run");
243 connect(a, SIGNAL(activated()), this, SLOT(intoBackground()));
244 a = new KAction(i18n("Step &into"), "pgmstep", Key_F8, m_debugger,
245 SLOT(programStep()), actionCollection(),
246 "exec_step_into");
247 connect(a, SIGNAL(activated()), this, SLOT(intoBackground()));
248 a = new KAction(i18n("Step &over"), "pgmnext", Key_F10, m_debugger,
249 SLOT(programNext()), actionCollection(),
250 "exec_step_over");
251 connect(a, SIGNAL(activated()), this, SLOT(intoBackground()));
252 a = new KAction(i18n("Step o&ut"), "pgmfinish", Key_F6, m_debugger,
253 SLOT(programFinish()), actionCollection(),
254 "exec_step_out");
255 connect(a, SIGNAL(activated()), this, SLOT(intoBackground()));
256 a = new KAction(i18n("Run to &cursor"), Key_F7, this,
257 SLOT(slotExecUntil()), actionCollection(),
258 "exec_run_to_cursor");
259 connect(a, SIGNAL(activated()), this, SLOT(intoBackground()));
260 a = new KAction(i18n("Step i&nto by instruction"), "pgmstepi",
261 SHIFT+Key_F8, m_debugger, SLOT(programStepi()),
262 actionCollection(), "exec_step_into_by_insn");
263 connect(a, SIGNAL(activated()), this, SLOT(intoBackground()));
264 a = new KAction(i18n("Step o&ver by instruction"), "pgmnexti",
265 SHIFT+Key_F10, m_debugger, SLOT(programNexti()),
266 actionCollection(), "exec_step_over_by_insn");
267 connect(a, SIGNAL(activated()), this, SLOT(intoBackground()));
268 (void)new KAction(i18n("&Program counter to current line"), 0,
269 m_filesWindow, SLOT(slotMoveProgramCounter()),
270 actionCollection(), "exec_movepc");
271 (void)new KAction(i18n("&Break"), 0, m_debugger,
272 SLOT(programBreak()), actionCollection(),
273 "exec_break");
274 (void)new KAction(i18n("&Kill"), 0, m_debugger,
275 SLOT(programKill()), actionCollection(),
276 "exec_kill");
277 (void)new KAction(i18n("Re&start"), 0, m_debugger,
278 SLOT(programRunAgain()), actionCollection(),
279 "exec_restart");
280 (void)new KAction(i18n("A&ttach..."), 0, this,
281 SLOT(slotExecAttach()), actionCollection(),
282 "exec_attach");
283 (void)new KAction(i18n("&Arguments..."), 0, this,
284 SLOT(slotExecArgs()), actionCollection(),
285 "exec_arguments");
287 // breakpoint menu
288 (void)new KAction(i18n("Set/Clear &breakpoint"), "brkpt", Key_F9,
289 m_filesWindow, SLOT(slotBrkptSet()), actionCollection(),
290 "breakpoint_set");
291 (void)new KAction(i18n("Set &temporary breakpoint"), SHIFT+Key_F9,
292 m_filesWindow, SLOT(slotBrkptSetTemp()), actionCollection(),
293 "breakpoint_set_temporary");
294 (void)new KAction(i18n("&Enable/Disable breakpoint"), CTRL+Key_F9,
295 m_filesWindow, SLOT(slotBrkptEnable()), actionCollection(),
296 "breakpoint_enable");
298 // only in popup menus
299 (void)new KAction(i18n("Watch Expression"), 0, this,
300 SLOT(slotLocalsToWatch()), actionCollection(),
301 "watch_expression");
302 (void)new KAction(i18n("Edit Value"), Key_F2, this,
303 SLOT(slotEditValue()), actionCollection(),
304 "edit_value");
306 (void)new KActionMenu(i18n("&Window"), actionCollection(), "window");
308 // all actions force an UI update
309 QValueList<KAction*> actions = actionCollection()->actions();
310 QValueList<KAction*>::Iterator it = actions.begin();
311 for (; it != actions.end(); ++it) {
312 connect(*it, SIGNAL(activated()), this, SLOT(updateUI()));
315 createGUI("kdbgui.rc");
318 void DebuggerMainWnd::initToolbar()
320 KToolBar* toolbar = toolBar("mainToolBar");
321 toolbar->setBarPos(KToolBar::Top);
322 //moveToolBar(toolbar);
324 toolbar->insertAnimatedWidget(ID_STATUS_BUSY,
325 actionCollection()->action("exec_break"), SLOT(activate()),
326 "pulse", -1);
327 toolbar->alignItemRight(ID_STATUS_BUSY, true);
328 m_animRunning = false;
330 KStatusBar* statusbar = statusBar();
331 statusbar->insertItem(m_statusActive, ID_STATUS_ACTIVE);
332 m_lastActiveStatusText = m_statusActive;
333 statusbar->insertItem(i18n("Line 00000"), ID_STATUS_LINENO);
334 statusbar->insertItem("", ID_STATUS_MSG); /* message pane */
336 // reserve some translations
337 i18n("Restart");
338 i18n("Core dump");
342 * We must override KTMainWindow's handling of close events since we have
343 * only one toplevel window, which lives on the stack (which KTMainWindow
344 * can't live with :-( )
346 void DebuggerMainWnd::closeEvent(QCloseEvent* e)
348 clearWFlags(WDestructiveClose);
350 if (m_debugger != 0) {
351 m_debugger->shutdown();
354 e->accept();
355 kapp->quit();
359 // instance properties
360 void DebuggerMainWnd::saveProperties(KConfig* config)
362 // session management
363 QString executable = "";
364 if (m_debugger != 0) {
365 executable = m_debugger->executable();
367 config->writeEntry("executable", executable);
370 void DebuggerMainWnd::readProperties(KConfig* config)
372 // session management
373 QString execName = config->readEntry("executable");
375 TRACE("readProperties: executable=" + execName);
376 if (!execName.isEmpty()) {
377 debugProgram(execName, "");
381 const char WindowGroup[] = "Windows";
382 const char RecentExecutables[] = "RecentExecutables";
384 void DebuggerMainWnd::saveSettings(KConfig* config)
386 KConfigGroupSaver g(config, WindowGroup);
388 writeDockConfig(config);
389 fixDockConfig(config, false); // downgrade
391 m_recentExecAction->saveEntries(config, RecentExecutables);
393 DebuggerMainWndBase::saveSettings(config);
396 void DebuggerMainWnd::restoreSettings(KConfig* config)
398 KConfigGroupSaver g(config, WindowGroup);
400 fixDockConfig(config, true); // upgrade
401 readDockConfig(config);
403 m_recentExecAction->loadEntries(config, RecentExecutables);
405 DebuggerMainWndBase::restoreSettings(config);
407 emit setTabWidth(m_tabWidth);
410 void DebuggerMainWnd::updateUI()
412 KToggleAction* viewFind =
413 static_cast<KToggleAction*>(actionCollection()->action("view_find"));
414 viewFind->setChecked(m_filesWindow->m_findDlg.isVisible());
415 viewFind->setEnabled(m_filesWindow->hasWindows());
416 actionCollection()->action("breakpoint_set")->setEnabled(m_debugger->canChangeBreakpoints());
417 actionCollection()->action("breakpoint_set_temporary")->setEnabled(m_debugger->canChangeBreakpoints());
418 actionCollection()->action("breakpoint_enable")->setEnabled(m_debugger->canChangeBreakpoints());
419 dockUpdateHelper("view_breakpoints", m_bpTable);
420 dockUpdateHelper("view_stack", m_btWindow);
421 dockUpdateHelper("view_locals", m_localVariables);
422 dockUpdateHelper("view_watched_expressions", m_watches);
423 dockUpdateHelper("view_registers", m_registers);
424 dockUpdateHelper("view_threads", m_threads);
425 dockUpdateHelper("view_memory", m_memoryWindow);
426 dockUpdateHelper("view_output", m_ttyWindow);
428 // AB: maybe in mainwndbase.cpp?
429 actionCollection()->action("file_executable")->setEnabled(m_debugger->isIdle());
430 actionCollection()->action("settings_program")->setEnabled(m_debugger->haveExecutable());
431 actionCollection()->action("file_core_dump")->setEnabled(m_debugger->canStart());
432 actionCollection()->action("exec_step_into")->setEnabled(m_debugger->canSingleStep());
433 actionCollection()->action("exec_step_into_by_insn")->setEnabled(m_debugger->canSingleStep());
434 actionCollection()->action("exec_step_over")->setEnabled(m_debugger->canSingleStep());
435 actionCollection()->action("exec_step_over_by_insn")->setEnabled(m_debugger->canSingleStep());
436 actionCollection()->action("exec_step_out")->setEnabled(m_debugger->canSingleStep());
437 actionCollection()->action("exec_run_to_cursor")->setEnabled(m_debugger->canSingleStep());
438 actionCollection()->action("exec_movepc")->setEnabled(m_debugger->canSingleStep());
439 actionCollection()->action("exec_restart")->setEnabled(m_debugger->canSingleStep());
440 actionCollection()->action("exec_attach")->setEnabled(m_debugger->isReady());
441 actionCollection()->action("exec_run")->setEnabled(m_debugger->canStart() || m_debugger->canSingleStep());
442 actionCollection()->action("exec_kill")->setEnabled(m_debugger->haveExecutable() && m_debugger->isProgramActive());
443 actionCollection()->action("exec_break")->setEnabled(m_debugger->isProgramRunning());
444 actionCollection()->action("exec_arguments")->setEnabled(m_debugger->haveExecutable());
445 actionCollection()->action("edit_value")->setEnabled(m_debugger->canSingleStep());
447 // animation
448 KAnimWidget* w = toolBar("mainToolBar")->animatedWidget(ID_STATUS_BUSY);
449 if (m_debugger->isIdle()) {
450 if (m_animRunning) {
451 w->stop();
452 m_animRunning = false;
454 } else {
455 if (!m_animRunning) {
456 w->start();
457 m_animRunning = true;
461 // update statusbar
462 QString newStatus;
463 if (m_debugger->isProgramActive())
464 newStatus = m_statusActive;
465 if (newStatus != m_lastActiveStatusText) {
466 statusBar()->changeItem(newStatus, ID_STATUS_ACTIVE);
467 m_lastActiveStatusText = newStatus;
469 // line number is updated in slotLineChanged
472 void DebuggerMainWnd::dockUpdateHelper(QString action, QWidget* w)
474 KToggleAction* item =
475 static_cast<KToggleAction*>(actionCollection()->action(action));
476 bool canChange = canChangeDockVisibility(w);
477 item->setEnabled(canChange);
478 item->setChecked(canChange && isDockVisible(w));
481 void DebuggerMainWnd::updateLineItems()
483 m_filesWindow->updateLineItems(m_debugger);
486 void DebuggerMainWnd::slotAddWatch()
488 if (m_debugger != 0) {
489 QString t = m_watches->watchText();
490 m_debugger->addWatch(t);
494 void DebuggerMainWnd::slotFileChanged()
496 // set caption
497 QString caption;
499 if (m_debugger->haveExecutable()) {
500 // basename part of executable
501 QString executable = m_debugger->executable();
502 const char* execBase = executable.data();
503 int lastSlash = executable.findRev('/');
504 if (lastSlash >= 0)
505 execBase += lastSlash + 1;
506 caption += execBase;
508 QString file;
509 int line;
510 bool anyWindows = m_filesWindow->activeLine(file, line);
511 updateLineStatus(anyWindows ? line : -1);
512 if (anyWindows) {
513 caption += " (";
514 caption += file;
515 caption += ")";
517 setCaption(caption);
520 void DebuggerMainWnd::slotLineChanged()
522 QString file;
523 int line;
524 bool anyWindows = m_filesWindow->activeLine(file, line);
525 updateLineStatus(anyWindows ? line : -1);
528 void DebuggerMainWnd::slotNewFileLoaded()
530 // updates program counter in the new file
531 if (m_debugger != 0)
532 m_filesWindow->updateLineItems(m_debugger);
535 void DebuggerMainWnd::updateLineStatus(int lineNo)
537 if (lineNo < 0) {
538 statusBar()->changeItem("", ID_STATUS_LINENO);
539 } else {
540 QString strLine;
541 strLine.sprintf(i18n("Line %d"), lineNo + 1);
542 statusBar()->changeItem(strLine, ID_STATUS_LINENO);
546 KDockWidget* DebuggerMainWnd::dockParent(QWidget* w)
548 while ((w = w->parentWidget()) != 0) {
549 if (w->isA("KDockWidget"))
550 return static_cast<KDockWidget*>(w);
552 return 0;
555 bool DebuggerMainWnd::isDockVisible(QWidget* w)
557 KDockWidget* d = dockParent(w);
558 return d != 0 && d->mayBeHide();
561 bool DebuggerMainWnd::canChangeDockVisibility(QWidget* w)
563 KDockWidget* d = dockParent(w);
564 return d != 0 && (d->mayBeHide() || d->mayBeShow());
567 // upgrades the entries from version 0.0.4 to 0.0.5 and back
568 void DebuggerMainWnd::fixDockConfig(KConfig* c, bool upgrade)
570 static const char dockGroup[] = "dock_setting_default";
571 if (!c->hasGroup(dockGroup))
572 return;
574 static const char oldVersion[] = "0.0.4";
575 static const char newVersion[] = "0.0.5";
576 const char* from = upgrade ? oldVersion : newVersion;
577 const char* to = upgrade ? newVersion : oldVersion;
578 QMap<QString,QString> e = c->entryMap(dockGroup);
579 if (e["Version"] != from)
580 return;
582 KConfigGroupSaver g(c, dockGroup);
583 c->writeEntry("Version", to);
584 TRACE(upgrade ? "upgrading dockconfig" : "downgrading dockconfig");
586 // turn all orientation entries from 0 to 1 and from 1 to 0
587 QMap<QString,QString>::Iterator i;
588 for (i = e.begin(); i != e.end(); ++i)
590 if (i.key().right(12) == ":orientation") {
591 TRACE("upgrading " + i.key() + " old value: " + *i);
592 int orientation = c->readNumEntry(i.key(), -1);
593 if (orientation >= 0) { // paranoia
594 c->writeEntry(i.key(), 1 - orientation);
600 TTYWindow* DebuggerMainWnd::ttyWindow()
602 return m_ttyWindow;
605 bool DebuggerMainWnd::debugProgram(const QString& exe, QCString lang)
607 // check the file name
608 QFileInfo fi(exe);
610 bool success = fi.isFile();
611 if (!success)
613 QString msg = i18n("`%1' is not a file or does not exist");
614 KMessageBox::sorry(this, msg.arg(exe));
616 else
618 success = DebuggerMainWndBase::debugProgram(fi.absFilePath(), lang, this);
621 if (success)
623 m_recentExecAction->addURL(KURL(fi.absFilePath()));
625 // keep the directory
626 m_lastDirectory = fi.dirPath(true);
627 m_filesWindow->setExtraDirectory(m_lastDirectory);
629 else
631 m_recentExecAction->removeURL(KURL(fi.absFilePath()));
634 return true;
637 void DebuggerMainWnd::slotNewStatusMsg()
639 newStatusMsg(statusBar());
642 void DebuggerMainWnd::slotFileGlobalSettings()
644 int oldTabWidth = m_tabWidth;
646 doGlobalOptions(this);
648 if (m_tabWidth != oldTabWidth) {
649 emit setTabWidth(m_tabWidth);
653 void DebuggerMainWnd::slotDebuggerStarting()
655 DebuggerMainWndBase::slotDebuggerStarting();
658 void DebuggerMainWnd::slotToggleBreak(const QString& fileName, int lineNo,
659 const DbgAddr& address, bool temp)
661 // lineNo is zero-based
662 if (m_debugger != 0) {
663 m_debugger->setBreakpoint(fileName, lineNo, address, temp);
667 void DebuggerMainWnd::slotEnaDisBreak(const QString& fileName, int lineNo,
668 const DbgAddr& address)
670 // lineNo is zero-based
671 if (m_debugger != 0) {
672 m_debugger->enableDisableBreakpoint(fileName, lineNo, address);
676 QString DebuggerMainWnd::createOutputWindow()
678 QString tty = DebuggerMainWndBase::createOutputWindow();
679 if (!tty.isEmpty()) {
680 connect(m_outputTermProc, SIGNAL(processExited(KProcess*)),
681 SLOT(slotTermEmuExited()));
683 return tty;
686 void DebuggerMainWnd::slotTermEmuExited()
688 shutdownTermWindow();
691 #include <X11/Xlib.h> /* XRaiseWindow, XLowerWindow */
693 void DebuggerMainWnd::slotProgramStopped()
695 // when the program stopped, move the window to the foreground
696 if (m_popForeground) {
697 ::XRaiseWindow(x11Display(), winId());
699 m_backTimer.stop();
702 void DebuggerMainWnd::intoBackground()
704 if (m_popForeground) {
705 m_backTimer.start(m_backTimeout, true); /* single-shot */
709 void DebuggerMainWnd::slotBackTimer()
711 ::XLowerWindow(x11Display(), winId());
714 void DebuggerMainWnd::slotRecentExec(const KURL& url)
716 QString exe = url.path();
717 debugProgram(exe, "");
720 QString DebuggerMainWnd::makeSourceFilter()
722 QString f;
723 f = m_sourceFilter + " " + m_headerFilter + i18n("|All source files\n");
724 f += m_sourceFilter + i18n("|Source files\n");
725 f += m_headerFilter + i18n("|Header files\n");
726 f += i18n("*|All files");
727 return f;
731 * Pop up the context menu in the locals window
733 void DebuggerMainWnd::slotLocalsPopup(int, const QPoint& pt)
735 QPopupMenu* popup =
736 static_cast<QPopupMenu*>(factory()->container("popup_locals", this));
737 if (popup == 0) {
738 return;
740 if (popup->isVisible()) {
741 popup->hide();
742 } else {
743 popup->popup(m_localVariables->mapToGlobal(pt));
748 * Copies the currently selected item to the watch window.
750 void DebuggerMainWnd::slotLocalsToWatch()
752 int idx = m_localVariables->currentItem();
754 if (idx >= 0 && m_debugger != 0) {
755 QString text = m_localVariables->exprStringAt(idx);
756 m_debugger->addWatch(text);
761 * Starts editing a value in a value display
763 void DebuggerMainWnd::slotEditValue()
765 // does one of the value trees have the focus
766 QWidget* f = kapp->focusWidget();
767 ExprWnd* wnd;
768 if (f == m_localVariables) {
769 wnd = m_localVariables;
770 } else if (f == m_watches->watchVariables()) {
771 wnd = m_watches->watchVariables();
772 } else {
773 return;
776 if (m_localVariables->isEditing() ||
777 m_watches->watchVariables()->isEditing())
779 return; /* don't edit twice */
782 int idx = wnd->currentItem();
783 if (idx >= 0 && m_debugger != 0 && m_debugger->canSingleStep())
785 TRACE("edit value");
786 // determine the text to edit
787 VarTree* expr = static_cast<VarTree*>(wnd->itemAt(idx));
788 QString text = m_debugger->driver()->editableValue(expr);
789 wnd->editValue(idx, text);
793 // Pop up the context menu of the files window (for loaded files)
794 void DebuggerMainWnd::slotFileWndMenu(const QPoint& pos)
796 QPopupMenu* popup =
797 static_cast<QPopupMenu*>(factory()->container("popup_files", this));
798 if (popup == 0) {
799 return;
801 if (popup->isVisible()) {
802 popup->hide();
803 } else {
804 // pos is still in widget coordinates of the sender
805 const QWidget* w = static_cast<const QWidget*>(sender());
806 popup->popup(w->mapToGlobal(pos));
810 // Pop up the context menu of the files window (while no file is loaded)
811 void DebuggerMainWnd::slotFileWndEmptyMenu(const QPoint& pos)
813 QPopupMenu* popup =
814 static_cast<QPopupMenu*>(factory()->container("popup_files_empty", this));
815 if (popup == 0) {
816 return;
818 if (popup->isVisible()) {
819 popup->hide();
820 } else {
821 // pos is still in widget coordinates of the sender
822 const QWidget* w = static_cast<const QWidget*>(sender());
823 popup->popup(w->mapToGlobal(pos));
827 void DebuggerMainWnd::slotFileOpen()
829 QString fileName = myGetFileName(i18n("Open"),
830 m_lastDirectory,
831 makeSourceFilter(), this);
833 if (!fileName.isEmpty())
835 QFileInfo fi(fileName);
836 m_lastDirectory = fi.dirPath();
837 m_filesWindow->setExtraDirectory(m_lastDirectory);
838 m_filesWindow->activateFile(fileName);
842 void DebuggerMainWnd::slotFileQuit()
844 if (m_debugger != 0) {
845 m_debugger->shutdown();
847 kapp->quit();
850 void DebuggerMainWnd::slotFileExe()
852 if (m_debugger->isIdle())
854 // open a new executable
855 QString executable = myGetFileName(i18n("Select the executable to debug"),
856 m_lastDirectory, 0, this);
857 if (executable.isEmpty())
858 return;
860 debugProgram(executable, "");
864 void DebuggerMainWnd::slotFileCore()
866 if (m_debugger->canStart())
868 QString corefile = myGetFileName(i18n("Select core dump"),
869 m_lastDirectory, 0, this);
870 if (!corefile.isEmpty()) {
871 m_debugger->useCoreFile(corefile, false);
876 void DebuggerMainWnd::slotFileProgSettings()
878 if (m_debugger != 0) {
879 m_debugger->programSettings(this);
883 void DebuggerMainWnd::slotViewToolbar()
885 if (toolBar()->isVisible())
886 toolBar()->hide();
887 else
888 toolBar()->show();
891 void DebuggerMainWnd::slotViewStatusbar()
893 if (statusBar()->isVisible())
894 statusBar()->hide();
895 else
896 statusBar()->show();
899 void DebuggerMainWnd::slotExecUntil()
901 if (m_debugger != 0)
903 QString file;
904 int lineNo;
905 if (m_filesWindow->activeLine(file, lineNo))
906 m_debugger->runUntil(file, lineNo);
910 void DebuggerMainWnd::slotExecAttach()
912 #ifdef PS_COMMAND
913 ProcAttachPS dlg(this);
914 #else
915 ProcAttach dlg(this);
916 dlg.setText(m_debugger->attachedPid());
917 #endif
918 if (dlg.exec()) {
919 m_debugger->attachProgram(dlg.text());
923 void DebuggerMainWnd::slotExecArgs()
925 if (m_debugger != 0) {
926 m_debugger->programArgs(this);
930 void DebuggerMainWnd::slotConfigureKeys()
932 KKeyDialog::configure(actionCollection(), this);
935 #include "dbgmainwnd.moc"