Accept text dropped onto the watches window.
[kdbg.git] / kdbg / dbgmainwnd.cpp
blob381a2ea67845ef2bda223180a178ff66537a7a94
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, i18n("Variable"), "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()));
87 connect(m_watches, SIGNAL(textDropped(const QString&)), SLOT(slotAddWatch(const QString&)));
89 KAction* windowMenu = actionCollection()->action("window");
90 m_filesWindow->setWindowMenu(static_cast<KActionMenu*>(windowMenu)->popupMenu());
91 connect(&m_filesWindow->m_findDlg, SIGNAL(closed()), SLOT(updateUI()));
92 connect(m_filesWindow, SIGNAL(newFileLoaded()),
93 SLOT(slotNewFileLoaded()));
94 connect(m_filesWindow, SIGNAL(toggleBreak(const QString&,int,const DbgAddr&,bool)),
95 this, SLOT(slotToggleBreak(const QString&,int,const DbgAddr&,bool)));
96 connect(m_filesWindow, SIGNAL(enadisBreak(const QString&,int,const DbgAddr&)),
97 this, SLOT(slotEnaDisBreak(const QString&,int,const DbgAddr&)));
98 connect(m_debugger, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)),
99 m_filesWindow, SLOT(activate(const QString&,int,const DbgAddr&)));
100 connect(m_debugger, SIGNAL(executableUpdated()),
101 m_filesWindow, SLOT(reloadAllFiles()));
102 connect(m_debugger, SIGNAL(updatePC(const QString&,int,const DbgAddr&,int)),
103 m_filesWindow, SLOT(updatePC(const QString&,int,const DbgAddr&,int)));
104 // value popup communication
105 connect(m_filesWindow, SIGNAL(initiateValuePopup(const QString&)),
106 m_debugger, SLOT(slotValuePopup(const QString&)));
107 connect(m_debugger, SIGNAL(valuePopup(const QString&)),
108 m_filesWindow, SLOT(slotShowValueTip(const QString&)));
109 // disassembling
110 connect(m_filesWindow, SIGNAL(disassemble(const QString&, int)),
111 m_debugger, SLOT(slotDisassemble(const QString&, int)));
112 connect(m_debugger, SIGNAL(disassembled(const QString&,int,const QList<DisassembledCode>&)),
113 m_filesWindow, SLOT(slotDisassembled(const QString&,int,const QList<DisassembledCode>&)));
114 connect(m_filesWindow, SIGNAL(moveProgramCounter(const QString&,int,const DbgAddr&)),
115 m_debugger, SLOT(setProgramCounter(const QString&,int,const DbgAddr&)));
116 // program stopped
117 connect(m_debugger, SIGNAL(programStopped()), SLOT(slotProgramStopped()));
118 connect(&m_backTimer, SIGNAL(timeout()), SLOT(slotBackTimer()));
119 // tab width
120 connect(this, SIGNAL(setTabWidth(int)), m_filesWindow, SIGNAL(setTabWidth(int)));
122 // Establish communication when right clicked on file window.
123 connect(m_filesWindow, SIGNAL(filesRightClick(const QPoint &)),
124 SLOT(slotFileWndMenu(const QPoint &)));
126 // Connection when right clicked on file window before any file is
127 // loaded.
128 connect(m_filesWindow, SIGNAL(clickedRight(const QPoint &)),
129 SLOT(slotFileWndEmptyMenu(const QPoint &)));
131 // file/line updates
132 connect(m_filesWindow, SIGNAL(fileChanged()), SLOT(slotFileChanged()));
133 connect(m_filesWindow, SIGNAL(lineChanged()), SLOT(slotLineChanged()));
135 // connect breakpoint table
136 connect(m_bpTable, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)),
137 m_filesWindow, SLOT(activate(const QString&,int,const DbgAddr&)));
138 connect(m_debugger, SIGNAL(updateUI()), m_bpTable, SLOT(updateUI()));
139 connect(m_debugger, SIGNAL(breakpointsChanged()), m_bpTable, SLOT(updateBreakList()));
140 connect(m_debugger, SIGNAL(breakpointsChanged()), m_bpTable, SLOT(updateUI()));
142 connect(m_debugger, SIGNAL(registersChanged(QList<RegisterInfo>&)),
143 m_registers, SLOT(updateRegisters(QList<RegisterInfo>&)));
145 connect(m_debugger, SIGNAL(memoryDumpChanged(const QString&, QList<MemoryDump>&)),
146 m_memoryWindow, SLOT(slotNewMemoryDump(const QString&, QList<MemoryDump>&)));
147 connect(m_debugger, SIGNAL(saveProgramSpecific(KConfigBase*)),
148 m_memoryWindow, SLOT(saveProgramSpecific(KConfigBase*)));
149 connect(m_debugger, SIGNAL(restoreProgramSpecific(KConfigBase*)),
150 m_memoryWindow, SLOT(restoreProgramSpecific(KConfigBase*)));
152 // thread window
153 connect(m_debugger, SIGNAL(threadsChanged(QList<ThreadInfo>&)),
154 m_threads, SLOT(updateThreads(QList<ThreadInfo>&)));
155 connect(m_threads, SIGNAL(setThread(int)),
156 m_debugger, SLOT(setThread(int)));
158 // view menu changes when docking state changes
159 connect(dockManager, SIGNAL(change()), SLOT(updateUI()));
161 // popup menu of the local variables window
162 connect(m_localVariables, SIGNAL(contextMenuRequested(QListViewItem*, const QPoint&, int)),
163 this, SLOT(slotLocalsPopup(QListViewItem*, const QPoint&)));
165 restoreSettings(kapp->config());
167 updateUI();
168 m_bpTable->updateUI();
169 slotFileChanged();
172 DebuggerMainWnd::~DebuggerMainWnd()
174 saveSettings(kapp->config());
175 // must delete m_debugger early since it references our windows
176 delete m_debugger;
177 m_debugger = 0;
179 delete m_memoryWindow;
180 delete m_threads;
181 delete m_ttyWindow;
182 delete m_bpTable;
183 delete m_registers;
184 delete m_watches;
185 delete m_localVariables;
186 delete m_btWindow;
187 delete m_filesWindow;
190 void DebuggerMainWnd::initKAction()
192 // file menu
193 KAction* open = KStdAction::open(this, SLOT(slotFileOpen()),
194 actionCollection());
195 open->setText(i18n("&Open Source..."));
196 (void)new KAction(i18n("&Reload Source"), "reload", 0, m_filesWindow,
197 SLOT(slotFileReload()), actionCollection(),
198 "file_reload");
199 (void)new KAction(i18n("&Executable..."), "execopen", 0, this,
200 SLOT(slotFileExe()), actionCollection(),
201 "file_executable");
202 m_recentExecAction = new KRecentFilesAction(i18n("Recent E&xecutables"), 0,
203 this, SLOT(slotRecentExec(const KURL&)),
204 actionCollection(), "file_executable_recent");
205 (void)new KAction(i18n("&Core dump..."), 0, this, SLOT(slotFileCore()),
206 actionCollection(), "file_core_dump");
207 KStdAction::quit(this, SLOT(slotFileQuit()), actionCollection());
209 // settings menu
210 (void)new KAction(i18n("This &Program..."), 0, this,
211 SLOT(slotFileProgSettings()), actionCollection(),
212 "settings_program");
213 (void)new KAction(i18n("&Global Options..."), 0, this,
214 SLOT(slotFileGlobalSettings()), actionCollection(),
215 "settings_global");
216 KStdAction::keyBindings(this, SLOT(slotConfigureKeys()), actionCollection());
217 KStdAction::showToolbar(this, SLOT(slotViewToolbar()), actionCollection());
218 KStdAction::showStatusbar(this, SLOT(slotViewStatusbar()), actionCollection());
220 // view menu
221 (void)new KToggleAction(i18n("&Find"), "find", CTRL+Key_F, m_filesWindow,
222 SLOT(slotViewFind()), actionCollection(),
223 "view_find");
224 i18n("Source &code");
225 struct { QString text; QWidget* w; QString id; } dw[] = {
226 { i18n("Stac&k"), m_btWindow, "view_stack"},
227 { i18n("&Locals"), m_localVariables, "view_locals"},
228 { i18n("&Watched expressions"), m_watches, "view_watched_expressions"},
229 { i18n("&Registers"), m_registers, "view_registers"},
230 { i18n("&Breakpoints"), m_bpTable, "view_breakpoints"},
231 { i18n("T&hreads"), m_threads, "view_threads"},
232 { i18n("&Output"), m_ttyWindow, "view_output"},
233 { i18n("&Memory"), m_memoryWindow, "view_memory"}
235 for (unsigned i = 0; i < sizeof(dw)/sizeof(dw[0]); i++) {
236 KDockWidget* d = dockParent(dw[i].w);
237 (void)new KToggleAction(dw[i].text, 0, d, SLOT(changeHideShowState()),
238 actionCollection(), dw[i].id);
242 // execution menu
243 KAction* a = new KAction(i18n("&Run"), "pgmrun", Key_F5, m_debugger,
244 SLOT(programRun()), actionCollection(), "exec_run");
245 connect(a, SIGNAL(activated()), this, SLOT(intoBackground()));
246 a = new KAction(i18n("Step &into"), "pgmstep", Key_F8, m_debugger,
247 SLOT(programStep()), actionCollection(),
248 "exec_step_into");
249 connect(a, SIGNAL(activated()), this, SLOT(intoBackground()));
250 a = new KAction(i18n("Step &over"), "pgmnext", Key_F10, m_debugger,
251 SLOT(programNext()), actionCollection(),
252 "exec_step_over");
253 connect(a, SIGNAL(activated()), this, SLOT(intoBackground()));
254 a = new KAction(i18n("Step o&ut"), "pgmfinish", Key_F6, m_debugger,
255 SLOT(programFinish()), actionCollection(),
256 "exec_step_out");
257 connect(a, SIGNAL(activated()), this, SLOT(intoBackground()));
258 a = new KAction(i18n("Run to &cursor"), Key_F7, this,
259 SLOT(slotExecUntil()), actionCollection(),
260 "exec_run_to_cursor");
261 connect(a, SIGNAL(activated()), this, SLOT(intoBackground()));
262 a = new KAction(i18n("Step i&nto by instruction"), "pgmstepi",
263 SHIFT+Key_F8, m_debugger, SLOT(programStepi()),
264 actionCollection(), "exec_step_into_by_insn");
265 connect(a, SIGNAL(activated()), this, SLOT(intoBackground()));
266 a = new KAction(i18n("Step o&ver by instruction"), "pgmnexti",
267 SHIFT+Key_F10, m_debugger, SLOT(programNexti()),
268 actionCollection(), "exec_step_over_by_insn");
269 connect(a, SIGNAL(activated()), this, SLOT(intoBackground()));
270 (void)new KAction(i18n("&Program counter to current line"), 0,
271 m_filesWindow, SLOT(slotMoveProgramCounter()),
272 actionCollection(), "exec_movepc");
273 (void)new KAction(i18n("&Break"), 0, m_debugger,
274 SLOT(programBreak()), actionCollection(),
275 "exec_break");
276 (void)new KAction(i18n("&Kill"), 0, m_debugger,
277 SLOT(programKill()), actionCollection(),
278 "exec_kill");
279 (void)new KAction(i18n("Re&start"), 0, m_debugger,
280 SLOT(programRunAgain()), actionCollection(),
281 "exec_restart");
282 (void)new KAction(i18n("A&ttach..."), 0, this,
283 SLOT(slotExecAttach()), actionCollection(),
284 "exec_attach");
285 (void)new KAction(i18n("&Arguments..."), 0, this,
286 SLOT(slotExecArgs()), actionCollection(),
287 "exec_arguments");
289 // breakpoint menu
290 (void)new KAction(i18n("Set/Clear &breakpoint"), "brkpt", Key_F9,
291 m_filesWindow, SLOT(slotBrkptSet()), actionCollection(),
292 "breakpoint_set");
293 (void)new KAction(i18n("Set &temporary breakpoint"), SHIFT+Key_F9,
294 m_filesWindow, SLOT(slotBrkptSetTemp()), actionCollection(),
295 "breakpoint_set_temporary");
296 (void)new KAction(i18n("&Enable/Disable breakpoint"), CTRL+Key_F9,
297 m_filesWindow, SLOT(slotBrkptEnable()), actionCollection(),
298 "breakpoint_enable");
300 // only in popup menus
301 (void)new KAction(i18n("Watch Expression"), 0, this,
302 SLOT(slotLocalsToWatch()), actionCollection(),
303 "watch_expression");
304 (void)new KAction(i18n("Edit Value"), Key_F2, this,
305 SLOT(slotEditValue()), actionCollection(),
306 "edit_value");
308 (void)new KActionMenu(i18n("&Window"), actionCollection(), "window");
310 // all actions force an UI update
311 QValueList<KAction*> actions = actionCollection()->actions();
312 QValueList<KAction*>::Iterator it = actions.begin();
313 for (; it != actions.end(); ++it) {
314 connect(*it, SIGNAL(activated()), this, SLOT(updateUI()));
317 createGUI("kdbgui.rc");
320 void DebuggerMainWnd::initToolbar()
322 KToolBar* toolbar = toolBar("mainToolBar");
323 toolbar->setBarPos(KToolBar::Top);
324 //moveToolBar(toolbar);
326 toolbar->insertAnimatedWidget(ID_STATUS_BUSY,
327 actionCollection()->action("exec_break"), SLOT(activate()),
328 "pulse", -1);
329 toolbar->alignItemRight(ID_STATUS_BUSY, true);
330 m_animRunning = false;
332 KStatusBar* statusbar = statusBar();
333 statusbar->insertItem(m_statusActive, ID_STATUS_ACTIVE);
334 m_lastActiveStatusText = m_statusActive;
335 statusbar->insertItem(i18n("Line 00000"), ID_STATUS_LINENO);
336 statusbar->insertItem("", ID_STATUS_MSG); /* message pane */
338 // reserve some translations
339 i18n("Restart");
340 i18n("Core dump");
344 * We must override KTMainWindow's handling of close events since we have
345 * only one toplevel window, which lives on the stack (which KTMainWindow
346 * can't live with :-( )
348 void DebuggerMainWnd::closeEvent(QCloseEvent* e)
350 clearWFlags(WDestructiveClose);
352 if (m_debugger != 0) {
353 m_debugger->shutdown();
356 e->accept();
357 kapp->quit();
361 // instance properties
362 void DebuggerMainWnd::saveProperties(KConfig* config)
364 // session management
365 QString executable = "";
366 if (m_debugger != 0) {
367 executable = m_debugger->executable();
369 config->writeEntry("executable", executable);
372 void DebuggerMainWnd::readProperties(KConfig* config)
374 // session management
375 QString execName = config->readEntry("executable");
377 TRACE("readProperties: executable=" + execName);
378 if (!execName.isEmpty()) {
379 debugProgram(execName, "");
383 const char WindowGroup[] = "Windows";
384 const char RecentExecutables[] = "RecentExecutables";
385 const char LastSession[] = "LastSession";
387 void DebuggerMainWnd::saveSettings(KConfig* config)
389 KConfigGroupSaver g(config, WindowGroup);
391 writeDockConfig(config);
392 fixDockConfig(config, false); // downgrade
394 m_recentExecAction->saveEntries(config, RecentExecutables);
396 KConfigGroupSaver g2(config, LastSession);
397 config->writeEntry("Width0Locals", m_localVariables->columnWidth(0));
398 config->writeEntry("Width0Watches", m_watches->columnWidth(0));
400 DebuggerMainWndBase::saveSettings(config);
403 void DebuggerMainWnd::restoreSettings(KConfig* config)
405 KConfigGroupSaver g(config, WindowGroup);
407 fixDockConfig(config, true); // upgrade
408 readDockConfig(config);
410 // Workaround bug #87787: KDockManager stores the titles of the KDockWidgets
411 // in the config files, although they are localized:
412 // If the user changes the language, the titles remain in the previous language.
413 struct { QString text; QWidget* w; } dw[] = {
414 { i18n("Stack"), m_btWindow },
415 { i18n("Locals"), m_localVariables },
416 { i18n("Watches"), m_watches },
417 { i18n("Registers"), m_registers },
418 { i18n("Breakpoints"), m_bpTable },
419 { i18n("Threads"), m_threads },
420 { i18n("Output"), m_ttyWindow },
421 { i18n("Memory"), m_memoryWindow }
423 for (int i = 0; i < int(sizeof(dw)/sizeof(dw[0])); i++)
425 KDockWidget* w = dockParent(dw[i].w);
426 w->setTabPageLabel(dw[i].text);
427 // this actually changes the captions in the tabs:
428 QEvent ev(QEvent::CaptionChange);
429 w->event(&ev);
432 m_recentExecAction->loadEntries(config, RecentExecutables);
434 KConfigGroupSaver g2(config, LastSession);
435 int w;
436 w = config->readNumEntry("Width0Locals", -1);
437 if (w >= 0 && w < 30000)
438 m_localVariables->setColumnWidth(0, w);
439 w = config->readNumEntry("Width0Watches", -1);
440 if (w >= 0 && w < 30000)
441 m_watches->setColumnWidth(0, w);
443 DebuggerMainWndBase::restoreSettings(config);
445 emit setTabWidth(m_tabWidth);
448 void DebuggerMainWnd::updateUI()
450 KToggleAction* viewFind =
451 static_cast<KToggleAction*>(actionCollection()->action("view_find"));
452 viewFind->setChecked(m_filesWindow->m_findDlg.isVisible());
453 viewFind->setEnabled(m_filesWindow->hasWindows());
454 actionCollection()->action("breakpoint_set")->setEnabled(m_debugger->canChangeBreakpoints());
455 actionCollection()->action("breakpoint_set_temporary")->setEnabled(m_debugger->canChangeBreakpoints());
456 actionCollection()->action("breakpoint_enable")->setEnabled(m_debugger->canChangeBreakpoints());
457 dockUpdateHelper("view_breakpoints", m_bpTable);
458 dockUpdateHelper("view_stack", m_btWindow);
459 dockUpdateHelper("view_locals", m_localVariables);
460 dockUpdateHelper("view_watched_expressions", m_watches);
461 dockUpdateHelper("view_registers", m_registers);
462 dockUpdateHelper("view_threads", m_threads);
463 dockUpdateHelper("view_memory", m_memoryWindow);
464 dockUpdateHelper("view_output", m_ttyWindow);
466 // AB: maybe in mainwndbase.cpp?
467 actionCollection()->action("file_executable")->setEnabled(m_debugger->isIdle());
468 actionCollection()->action("settings_program")->setEnabled(m_debugger->haveExecutable());
469 actionCollection()->action("file_core_dump")->setEnabled(m_debugger->canStart());
470 actionCollection()->action("exec_step_into")->setEnabled(m_debugger->canSingleStep());
471 actionCollection()->action("exec_step_into_by_insn")->setEnabled(m_debugger->canSingleStep());
472 actionCollection()->action("exec_step_over")->setEnabled(m_debugger->canSingleStep());
473 actionCollection()->action("exec_step_over_by_insn")->setEnabled(m_debugger->canSingleStep());
474 actionCollection()->action("exec_step_out")->setEnabled(m_debugger->canSingleStep());
475 actionCollection()->action("exec_run_to_cursor")->setEnabled(m_debugger->canSingleStep());
476 actionCollection()->action("exec_movepc")->setEnabled(m_debugger->canSingleStep());
477 actionCollection()->action("exec_restart")->setEnabled(m_debugger->canSingleStep());
478 actionCollection()->action("exec_attach")->setEnabled(m_debugger->isReady());
479 actionCollection()->action("exec_run")->setEnabled(m_debugger->canStart() || m_debugger->canSingleStep());
480 actionCollection()->action("exec_kill")->setEnabled(m_debugger->haveExecutable() && m_debugger->isProgramActive());
481 actionCollection()->action("exec_break")->setEnabled(m_debugger->isProgramRunning());
482 actionCollection()->action("exec_arguments")->setEnabled(m_debugger->haveExecutable());
483 actionCollection()->action("edit_value")->setEnabled(m_debugger->canSingleStep());
485 // animation
486 KAnimWidget* w = toolBar("mainToolBar")->animatedWidget(ID_STATUS_BUSY);
487 if (m_debugger->isIdle()) {
488 if (m_animRunning) {
489 w->stop();
490 m_animRunning = false;
492 } else {
493 if (!m_animRunning) {
494 w->start();
495 m_animRunning = true;
499 // update statusbar
500 QString newStatus;
501 if (m_debugger->isProgramActive())
502 newStatus = m_statusActive;
503 if (newStatus != m_lastActiveStatusText) {
504 statusBar()->changeItem(newStatus, ID_STATUS_ACTIVE);
505 m_lastActiveStatusText = newStatus;
507 // line number is updated in slotLineChanged
510 void DebuggerMainWnd::dockUpdateHelper(QString action, QWidget* w)
512 KToggleAction* item =
513 static_cast<KToggleAction*>(actionCollection()->action(action));
514 bool canChange = canChangeDockVisibility(w);
515 item->setEnabled(canChange);
516 item->setChecked(canChange && isDockVisible(w));
519 void DebuggerMainWnd::updateLineItems()
521 m_filesWindow->updateLineItems(m_debugger);
524 void DebuggerMainWnd::slotAddWatch()
526 if (m_debugger != 0) {
527 QString t = m_watches->watchText();
528 m_debugger->addWatch(t);
532 void DebuggerMainWnd::slotAddWatch(const QString& text)
534 if (m_debugger != 0) {
535 m_debugger->addWatch(text);
539 void DebuggerMainWnd::slotFileChanged()
541 // set caption
542 QString caption;
544 if (m_debugger->haveExecutable()) {
545 // basename part of executable
546 QString executable = m_debugger->executable();
547 const char* execBase = executable.data();
548 int lastSlash = executable.findRev('/');
549 if (lastSlash >= 0)
550 execBase += lastSlash + 1;
551 caption += execBase;
553 QString file;
554 int line;
555 bool anyWindows = m_filesWindow->activeLine(file, line);
556 updateLineStatus(anyWindows ? line : -1);
557 if (anyWindows) {
558 caption += " (";
559 caption += file;
560 caption += ")";
562 setCaption(caption);
565 void DebuggerMainWnd::slotLineChanged()
567 QString file;
568 int line;
569 bool anyWindows = m_filesWindow->activeLine(file, line);
570 updateLineStatus(anyWindows ? line : -1);
573 void DebuggerMainWnd::slotNewFileLoaded()
575 // updates program counter in the new file
576 if (m_debugger != 0)
577 m_filesWindow->updateLineItems(m_debugger);
580 void DebuggerMainWnd::updateLineStatus(int lineNo)
582 if (lineNo < 0) {
583 statusBar()->changeItem("", ID_STATUS_LINENO);
584 } else {
585 QString strLine;
586 strLine.sprintf(i18n("Line %d"), lineNo + 1);
587 statusBar()->changeItem(strLine, ID_STATUS_LINENO);
591 KDockWidget* DebuggerMainWnd::dockParent(QWidget* w)
593 while ((w = w->parentWidget()) != 0) {
594 if (w->isA("KDockWidget"))
595 return static_cast<KDockWidget*>(w);
597 return 0;
600 bool DebuggerMainWnd::isDockVisible(QWidget* w)
602 KDockWidget* d = dockParent(w);
603 return d != 0 && d->mayBeHide();
606 bool DebuggerMainWnd::canChangeDockVisibility(QWidget* w)
608 KDockWidget* d = dockParent(w);
609 return d != 0 && (d->mayBeHide() || d->mayBeShow());
612 // upgrades the entries from version 0.0.4 to 0.0.5 and back
613 void DebuggerMainWnd::fixDockConfig(KConfig* c, bool upgrade)
615 static const char dockGroup[] = "dock_setting_default";
616 if (!c->hasGroup(dockGroup))
617 return;
619 static const char oldVersion[] = "0.0.4";
620 static const char newVersion[] = "0.0.5";
621 const char* from = upgrade ? oldVersion : newVersion;
622 const char* to = upgrade ? newVersion : oldVersion;
623 QMap<QString,QString> e = c->entryMap(dockGroup);
624 if (e["Version"] != from)
625 return;
627 KConfigGroupSaver g(c, dockGroup);
628 c->writeEntry("Version", to);
629 TRACE(upgrade ? "upgrading dockconfig" : "downgrading dockconfig");
631 // turn all orientation entries from 0 to 1 and from 1 to 0
632 QMap<QString,QString>::Iterator i;
633 for (i = e.begin(); i != e.end(); ++i)
635 if (i.key().right(12) == ":orientation") {
636 TRACE("upgrading " + i.key() + " old value: " + *i);
637 int orientation = c->readNumEntry(i.key(), -1);
638 if (orientation >= 0) { // paranoia
639 c->writeEntry(i.key(), 1 - orientation);
645 TTYWindow* DebuggerMainWnd::ttyWindow()
647 return m_ttyWindow;
650 bool DebuggerMainWnd::debugProgram(const QString& exe, QCString lang)
652 // check the file name
653 QFileInfo fi(exe);
655 bool success = fi.isFile();
656 if (!success)
658 QString msg = i18n("`%1' is not a file or does not exist");
659 KMessageBox::sorry(this, msg.arg(exe));
661 else
663 success = DebuggerMainWndBase::debugProgram(fi.absFilePath(), lang, this);
666 if (success)
668 m_recentExecAction->addURL(KURL(fi.absFilePath()));
670 // keep the directory
671 m_lastDirectory = fi.dirPath(true);
672 m_filesWindow->setExtraDirectory(m_lastDirectory);
674 else
676 m_recentExecAction->removeURL(KURL(fi.absFilePath()));
679 return true;
682 void DebuggerMainWnd::slotNewStatusMsg()
684 newStatusMsg(statusBar());
687 void DebuggerMainWnd::slotFileGlobalSettings()
689 int oldTabWidth = m_tabWidth;
691 doGlobalOptions(this);
693 if (m_tabWidth != oldTabWidth) {
694 emit setTabWidth(m_tabWidth);
698 void DebuggerMainWnd::slotDebuggerStarting()
700 DebuggerMainWndBase::slotDebuggerStarting();
703 void DebuggerMainWnd::slotToggleBreak(const QString& fileName, int lineNo,
704 const DbgAddr& address, bool temp)
706 // lineNo is zero-based
707 if (m_debugger != 0) {
708 m_debugger->setBreakpoint(fileName, lineNo, address, temp);
712 void DebuggerMainWnd::slotEnaDisBreak(const QString& fileName, int lineNo,
713 const DbgAddr& address)
715 // lineNo is zero-based
716 if (m_debugger != 0) {
717 m_debugger->enableDisableBreakpoint(fileName, lineNo, address);
721 QString DebuggerMainWnd::createOutputWindow()
723 QString tty = DebuggerMainWndBase::createOutputWindow();
724 if (!tty.isEmpty()) {
725 connect(m_outputTermProc, SIGNAL(processExited(KProcess*)),
726 SLOT(slotTermEmuExited()));
728 return tty;
731 void DebuggerMainWnd::slotTermEmuExited()
733 shutdownTermWindow();
736 void DebuggerMainWnd::slotProgramStopped()
738 // when the program stopped, move the window to the foreground
739 if (m_popForeground) {
740 // unfortunately, this requires quite some force to work :-(
741 KWin::raiseWindow(winId());
742 KWin::forceActiveWindow(winId());
744 m_backTimer.stop();
747 void DebuggerMainWnd::intoBackground()
749 if (m_popForeground) {
750 m_backTimer.start(m_backTimeout, true); /* single-shot */
754 void DebuggerMainWnd::slotBackTimer()
756 lower();
759 void DebuggerMainWnd::slotRecentExec(const KURL& url)
761 QString exe = url.path();
762 debugProgram(exe, "");
765 QString DebuggerMainWnd::makeSourceFilter()
767 QString f;
768 f = m_sourceFilter + " " + m_headerFilter + i18n("|All source files\n");
769 f += m_sourceFilter + i18n("|Source files\n");
770 f += m_headerFilter + i18n("|Header files\n");
771 f += i18n("*|All files");
772 return f;
776 * Pop up the context menu in the locals window
778 void DebuggerMainWnd::slotLocalsPopup(QListViewItem*, const QPoint& pt)
780 QPopupMenu* popup =
781 static_cast<QPopupMenu*>(factory()->container("popup_locals", this));
782 if (popup == 0) {
783 return;
785 if (popup->isVisible()) {
786 popup->hide();
787 } else {
788 popup->popup(pt);
793 * Copies the currently selected item to the watch window.
795 void DebuggerMainWnd::slotLocalsToWatch()
797 VarTree* item = m_localVariables->selectedItem();
799 if (item != 0 && m_debugger != 0) {
800 QString text = item->computeExpr();
801 m_debugger->addWatch(text);
806 * Starts editing a value in a value display
808 void DebuggerMainWnd::slotEditValue()
810 // does one of the value trees have the focus
811 QWidget* f = kapp->focusWidget();
812 ExprWnd* wnd;
813 if (f == m_localVariables) {
814 wnd = m_localVariables;
815 } else if (f == m_watches->watchVariables()) {
816 wnd = m_watches->watchVariables();
817 } else {
818 return;
821 if (m_localVariables->isEditing() ||
822 m_watches->watchVariables()->isEditing())
824 return; /* don't edit twice */
827 VarTree* expr = wnd->currentItem();
828 if (expr != 0 && m_debugger != 0 && m_debugger->canSingleStep())
830 TRACE("edit value");
831 // determine the text to edit
832 QString text = m_debugger->driver()->editableValue(expr);
833 wnd->editValue(expr, text);
837 // Pop up the context menu of the files window (for loaded files)
838 void DebuggerMainWnd::slotFileWndMenu(const QPoint& pos)
840 QPopupMenu* popup =
841 static_cast<QPopupMenu*>(factory()->container("popup_files", this));
842 if (popup == 0) {
843 return;
845 if (popup->isVisible()) {
846 popup->hide();
847 } else {
848 // pos is still in widget coordinates of the sender
849 const QWidget* w = static_cast<const QWidget*>(sender());
850 popup->popup(w->mapToGlobal(pos));
854 // Pop up the context menu of the files window (while no file is loaded)
855 void DebuggerMainWnd::slotFileWndEmptyMenu(const QPoint& pos)
857 QPopupMenu* popup =
858 static_cast<QPopupMenu*>(factory()->container("popup_files_empty", this));
859 if (popup == 0) {
860 return;
862 if (popup->isVisible()) {
863 popup->hide();
864 } else {
865 // pos is still in widget coordinates of the sender
866 const QWidget* w = static_cast<const QWidget*>(sender());
867 popup->popup(w->mapToGlobal(pos));
871 void DebuggerMainWnd::slotFileOpen()
873 // start browsing in the active file's directory
874 // fall back to last used directory (executable)
875 QString dir = m_lastDirectory;
876 QString fileName = m_filesWindow->activeFileName();
877 if (!fileName.isEmpty()) {
878 QFileInfo fi(fileName);
879 dir = fi.dirPath();
882 fileName = myGetFileName(i18n("Open"),
883 dir,
884 makeSourceFilter(), this);
886 if (!fileName.isEmpty())
888 QFileInfo fi(fileName);
889 m_lastDirectory = fi.dirPath();
890 m_filesWindow->setExtraDirectory(m_lastDirectory);
891 m_filesWindow->activateFile(fileName);
895 void DebuggerMainWnd::slotFileQuit()
897 if (m_debugger != 0) {
898 m_debugger->shutdown();
900 kapp->quit();
903 void DebuggerMainWnd::slotFileExe()
905 if (m_debugger->isIdle())
907 // open a new executable
908 QString executable = myGetFileName(i18n("Select the executable to debug"),
909 m_lastDirectory, 0, this);
910 if (executable.isEmpty())
911 return;
913 debugProgram(executable, "");
917 void DebuggerMainWnd::slotFileCore()
919 if (m_debugger->canStart())
921 QString corefile = myGetFileName(i18n("Select core dump"),
922 m_lastDirectory, 0, this);
923 if (!corefile.isEmpty()) {
924 m_debugger->useCoreFile(corefile, false);
929 void DebuggerMainWnd::slotFileProgSettings()
931 if (m_debugger != 0) {
932 m_debugger->programSettings(this);
936 void DebuggerMainWnd::slotViewToolbar()
938 if (toolBar()->isVisible())
939 toolBar()->hide();
940 else
941 toolBar()->show();
944 void DebuggerMainWnd::slotViewStatusbar()
946 if (statusBar()->isVisible())
947 statusBar()->hide();
948 else
949 statusBar()->show();
952 void DebuggerMainWnd::slotExecUntil()
954 if (m_debugger != 0)
956 QString file;
957 int lineNo;
958 if (m_filesWindow->activeLine(file, lineNo))
959 m_debugger->runUntil(file, lineNo);
963 void DebuggerMainWnd::slotExecAttach()
965 #ifdef PS_COMMAND
966 ProcAttachPS dlg(this);
967 // seed filter with executable name
968 QFileInfo fi = m_debugger->executable();
969 dlg.filterEdit->setText(fi.fileName());
970 #else
971 ProcAttach dlg(this);
972 dlg.setText(m_debugger->attachedPid());
973 #endif
974 if (dlg.exec()) {
975 m_debugger->attachProgram(dlg.text());
979 void DebuggerMainWnd::slotExecArgs()
981 if (m_debugger != 0) {
982 m_debugger->programArgs(this);
986 void DebuggerMainWnd::slotConfigureKeys()
988 KKeyDialog::configure(actionCollection(), this);
991 #include "dbgmainwnd.moc"