You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kdbg/kdbg/dbgmainwnd.cpp

877 lines
29 KiB

/*
* Copyright Johannes Sixt
* This file is licensed under the GNU General Public License Version 2.
* See the file COPYING in the toplevel directory of the source directory.
*/
#include <tdeapplication.h>
#include <tdelocale.h> /* i18n */
#include <tdemessagebox.h>
#include <tdeconfig.h>
#include <kstatusbar.h>
#include <kiconloader.h>
#include <tdestdaccel.h>
#include <kstdaction.h>
#include <tdeaction.h>
#include <tdepopupmenu.h>
#include <tdefiledialog.h>
#include <kprocess.h>
#include <kkeydialog.h>
#include <kanimwidget.h>
#include <twin.h>
#include <ntqlistbox.h>
#include <ntqfileinfo.h>
#include "dbgmainwnd.h"
#include "debugger.h"
#include "commandids.h"
#include "winstack.h"
#include "brkpt.h"
#include "threadlist.h"
#include "memwindow.h"
#include "ttywnd.h"
#include "procattach.h"
#include "dbgdriver.h"
#include "mydebug.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
DebuggerMainWnd::DebuggerMainWnd(const char* name) :
KDockMainWindow(0, name),
DebuggerMainWndBase()
{
TQPixmap p;
KDockWidget* dw0 = createDockWidget("Source", p, 0, i18n("Source"));
m_filesWindow = new WinStack(dw0, "files");
dw0->setWidget(m_filesWindow);
dw0->setDockSite(KDockWidget::DockCorner);
dw0->setEnableDocking(KDockWidget::DockNone);
setView(dw0);
setMainDockWidget(dw0);
KDockWidget* dw1 = createDockWidget("Stack", p, 0, i18n("Stack"));
m_btWindow = new TQListBox(dw1, "backtrace");
dw1->setWidget(m_btWindow);
KDockWidget* dw2 = createDockWidget("Locals", p, 0, i18n("Locals"));
m_localVariables = new ExprWnd(dw2, i18n("Variable"), "locals");
dw2->setWidget(m_localVariables);
KDockWidget* dw3 = createDockWidget("Watches", p, 0, i18n("Watches"));
m_watches = new WatchWindow(dw3, "watches");
dw3->setWidget(m_watches);
KDockWidget* dw4 = createDockWidget("Registers", p, 0, i18n("Registers"));
m_registers = new RegisterView(dw4, "registers");
dw4->setWidget(m_registers);
KDockWidget* dw5 = createDockWidget("Breakpoints", p, 0, i18n("Breakpoints"));
m_bpTable = new BreakpointTable(dw5, "breakpoints");
dw5->setWidget(m_bpTable);
KDockWidget* dw6 = createDockWidget("Output", p, 0, i18n("Output"));
m_ttyWindow = new TTYWindow(dw6, "output");
dw6->setWidget(m_ttyWindow);
KDockWidget* dw7 = createDockWidget("Threads", p, 0, i18n("Threads"));
m_threads = new ThreadList(dw7, "threads");
dw7->setWidget(m_threads);
KDockWidget* dw8 = createDockWidget("Memory", p, 0, i18n("Memory"));
m_memoryWindow = new MemoryWindow(dw8, "memory");
dw8->setWidget(m_memoryWindow);
setupDebugger(this, m_localVariables, m_watches->watchVariables(), m_btWindow);
m_bpTable->setDebugger(m_debugger);
m_memoryWindow->setDebugger(m_debugger);
setStandardToolBarMenuEnabled(true);
initKAction();
initToolbar(); // kind of obsolete?
connect(m_watches, TQ_SIGNAL(addWatch()), TQ_SLOT(slotAddWatch()));
connect(m_watches, TQ_SIGNAL(deleteWatch()), m_debugger, TQ_SLOT(slotDeleteWatch()));
connect(m_watches, TQ_SIGNAL(textDropped(const TQString&)), TQ_SLOT(slotAddWatch(const TQString&)));
connect(&m_filesWindow->m_findDlg, TQ_SIGNAL(closed()), TQ_SLOT(updateUI()));
connect(m_filesWindow, TQ_SIGNAL(newFileLoaded()),
TQ_SLOT(slotNewFileLoaded()));
connect(m_filesWindow, TQ_SIGNAL(toggleBreak(const TQString&,int,const DbgAddr&,bool)),
this, TQ_SLOT(slotToggleBreak(const TQString&,int,const DbgAddr&,bool)));
connect(m_filesWindow, TQ_SIGNAL(enadisBreak(const TQString&,int,const DbgAddr&)),
this, TQ_SLOT(slotEnaDisBreak(const TQString&,int,const DbgAddr&)));
connect(m_debugger, TQ_SIGNAL(activateFileLine(const TQString&,int,const DbgAddr&)),
m_filesWindow, TQ_SLOT(activate(const TQString&,int,const DbgAddr&)));
connect(m_debugger, TQ_SIGNAL(executableUpdated()),
m_filesWindow, TQ_SLOT(reloadAllFiles()));
connect(m_debugger, TQ_SIGNAL(updatePC(const TQString&,int,const DbgAddr&,int)),
m_filesWindow, TQ_SLOT(updatePC(const TQString&,int,const DbgAddr&,int)));
// value popup communication
connect(m_filesWindow, TQ_SIGNAL(initiateValuePopup(const TQString&)),
m_debugger, TQ_SLOT(slotValuePopup(const TQString&)));
connect(m_debugger, TQ_SIGNAL(valuePopup(const TQString&)),
m_filesWindow, TQ_SLOT(slotShowValueTip(const TQString&)));
// disassembling
connect(m_filesWindow, TQ_SIGNAL(disassemble(const TQString&, int)),
m_debugger, TQ_SLOT(slotDisassemble(const TQString&, int)));
connect(m_debugger, TQ_SIGNAL(disassembled(const TQString&,int,const std::list<DisassembledCode>&)),
m_filesWindow, TQ_SLOT(slotDisassembled(const TQString&,int,const std::list<DisassembledCode>&)));
connect(m_filesWindow, TQ_SIGNAL(moveProgramCounter(const TQString&,int,const DbgAddr&)),
m_debugger, TQ_SLOT(setProgramCounter(const TQString&,int,const DbgAddr&)));
// program stopped
connect(m_debugger, TQ_SIGNAL(programStopped()), TQ_SLOT(slotProgramStopped()));
connect(&m_backTimer, TQ_SIGNAL(timeout()), TQ_SLOT(slotBackTimer()));
// tab width
connect(this, TQ_SIGNAL(setTabWidth(int)), m_filesWindow, TQ_SIGNAL(setTabWidth(int)));
// connect breakpoint table
connect(m_bpTable, TQ_SIGNAL(activateFileLine(const TQString&,int,const DbgAddr&)),
m_filesWindow, TQ_SLOT(activate(const TQString&,int,const DbgAddr&)));
connect(m_debugger, TQ_SIGNAL(updateUI()), m_bpTable, TQ_SLOT(updateUI()));
connect(m_debugger, TQ_SIGNAL(breakpointsChanged()), m_bpTable, TQ_SLOT(updateBreakList()));
connect(m_debugger, TQ_SIGNAL(breakpointsChanged()), m_bpTable, TQ_SLOT(updateUI()));
connect(m_debugger, TQ_SIGNAL(registersChanged(const std::list<RegisterInfo>&)),
m_registers, TQ_SLOT(updateRegisters(const std::list<RegisterInfo>&)));
connect(m_debugger, TQ_SIGNAL(memoryDumpChanged(const TQString&, const std::list<MemoryDump>&)),
m_memoryWindow, TQ_SLOT(slotNewMemoryDump(const TQString&, const std::list<MemoryDump>&)));
connect(m_debugger, TQ_SIGNAL(saveProgramSpecific(TDEConfigBase*)),
m_memoryWindow, TQ_SLOT(saveProgramSpecific(TDEConfigBase*)));
connect(m_debugger, TQ_SIGNAL(restoreProgramSpecific(TDEConfigBase*)),
m_memoryWindow, TQ_SLOT(restoreProgramSpecific(TDEConfigBase*)));
// thread window
connect(m_debugger, TQ_SIGNAL(threadsChanged(const std::list<ThreadInfo>&)),
m_threads, TQ_SLOT(updateThreads(const std::list<ThreadInfo>&)));
connect(m_threads, TQ_SIGNAL(setThread(int)),
m_debugger, TQ_SLOT(setThread(int)));
// view menu changes when docking state changes
connect(dockManager, TQ_SIGNAL(change()), TQ_SLOT(updateUI()));
// popup menu of the local variables window
connect(m_localVariables, TQ_SIGNAL(contextMenuRequested(TQListViewItem*, const TQPoint&, int)),
this, TQ_SLOT(slotLocalsPopup(TQListViewItem*, const TQPoint&)));
restoreSettings(kapp->config());
updateUI();
m_bpTable->updateUI();
}
DebuggerMainWnd::~DebuggerMainWnd()
{
saveSettings(kapp->config());
// must delete m_debugger early since it references our windows
delete m_debugger;
m_debugger = 0;
delete m_memoryWindow;
delete m_threads;
delete m_ttyWindow;
delete m_bpTable;
delete m_registers;
delete m_watches;
delete m_localVariables;
delete m_btWindow;
delete m_filesWindow;
}
void DebuggerMainWnd::initKAction()
{
// file menu
TDEAction* open = KStdAction::open(this, TQ_SLOT(slotFileOpen()),
actionCollection());
open->setText(i18n("&Open Source..."));
KStdAction::close(m_filesWindow, TQ_SLOT(slotClose()), actionCollection());
(void)new TDEAction(i18n("&Reload Source"), "reload", 0, m_filesWindow,
TQ_SLOT(slotFileReload()), actionCollection(),
"file_reload");
(void)new TDEAction(i18n("&Executable..."), "execopen", 0, this,
TQ_SLOT(slotFileExe()), actionCollection(),
"file_executable");
m_recentExecAction = new TDERecentFilesAction(i18n("Recent E&xecutables"), 0,
this, TQ_SLOT(slotRecentExec(const KURL&)),
actionCollection(), "file_executable_recent");
(void)new TDEAction(i18n("&Core dump..."), 0, this, TQ_SLOT(slotFileCore()),
actionCollection(), "file_core_dump");
KStdAction::quit(kapp, TQ_SLOT(closeAllWindows()), actionCollection());
// settings menu
(void)new TDEAction(i18n("This &Program..."), 0, this,
TQ_SLOT(slotFileProgSettings()), actionCollection(),
"settings_program");
(void)new TDEAction(i18n("&Global Options..."), 0, this,
TQ_SLOT(slotFileGlobalSettings()), actionCollection(),
"settings_global");
KStdAction::keyBindings(this, TQ_SLOT(slotConfigureKeys()), actionCollection());
KStdAction::showStatusbar(this, TQ_SLOT(slotViewStatusbar()), actionCollection());
// view menu
(void)new TDEToggleAction(i18n("&Find"), "edit-find", CTRL+Key_F, m_filesWindow,
TQ_SLOT(slotViewFind()), actionCollection(),
"view_find");
(void)KStdAction::findNext(m_filesWindow, TQ_SLOT(slotFindForward()), actionCollection(), "view_findnext");
(void)KStdAction::findPrev(m_filesWindow, TQ_SLOT(slotFindBackward()), actionCollection(), "view_findprev");
i18n("Source &code");
struct { TQString text; TQWidget* w; TQString id; } dw[] = {
{ i18n("Stac&k"), m_btWindow, "view_stack"},
{ i18n("&Locals"), m_localVariables, "view_locals"},
{ i18n("&Watched expressions"), m_watches, "view_watched_expressions"},
{ i18n("&Registers"), m_registers, "view_registers"},
{ i18n("&Breakpoints"), m_bpTable, "view_breakpoints"},
{ i18n("T&hreads"), m_threads, "view_threads"},
{ i18n("&Output"), m_ttyWindow, "view_output"},
{ i18n("&Memory"), m_memoryWindow, "view_memory"}
};
for (unsigned i = 0; i < sizeof(dw)/sizeof(dw[0]); i++) {
KDockWidget* d = dockParent(dw[i].w);
(void)new TDEToggleAction(dw[i].text, 0, d, TQ_SLOT(changeHideShowState()),
actionCollection(), dw[i].id.latin1());
}
// execution menu
TDEAction* a = new TDEAction(i18n("&Run"), "pgmrun", Key_F5, m_debugger,
TQ_SLOT(programRun()), actionCollection(), "exec_run");
connect(a, TQ_SIGNAL(activated()), this, TQ_SLOT(intoBackground()));
a = new TDEAction(i18n("Step &into"), "pgmstep", Key_F8, m_debugger,
TQ_SLOT(programStep()), actionCollection(),
"exec_step_into");
connect(a, TQ_SIGNAL(activated()), this, TQ_SLOT(intoBackground()));
a = new TDEAction(i18n("Step &over"), "pgmnext", Key_F10, m_debugger,
TQ_SLOT(programNext()), actionCollection(),
"exec_step_over");
connect(a, TQ_SIGNAL(activated()), this, TQ_SLOT(intoBackground()));
a = new TDEAction(i18n("Step o&ut"), "pgmfinish", Key_F6, m_debugger,
TQ_SLOT(programFinish()), actionCollection(),
"exec_step_out");
connect(a, TQ_SIGNAL(activated()), this, TQ_SLOT(intoBackground()));
a = new TDEAction(i18n("Run to &cursor"), Key_F7, this,
TQ_SLOT(slotExecUntil()), actionCollection(),
"exec_run_to_cursor");
connect(a, TQ_SIGNAL(activated()), this, TQ_SLOT(intoBackground()));
a = new TDEAction(i18n("Step i&nto by instruction"), "pgmstepi",
SHIFT+Key_F8, m_debugger, TQ_SLOT(programStepi()),
actionCollection(), "exec_step_into_by_insn");
connect(a, TQ_SIGNAL(activated()), this, TQ_SLOT(intoBackground()));
a = new TDEAction(i18n("Step o&ver by instruction"), "pgmnexti",
SHIFT+Key_F10, m_debugger, TQ_SLOT(programNexti()),
actionCollection(), "exec_step_over_by_insn");
connect(a, TQ_SIGNAL(activated()), this, TQ_SLOT(intoBackground()));
(void)new TDEAction(i18n("&Program counter to current line"), 0,
m_filesWindow, TQ_SLOT(slotMoveProgramCounter()),
actionCollection(), "exec_movepc");
(void)new TDEAction(i18n("&Break"), 0, m_debugger,
TQ_SLOT(programBreak()), actionCollection(),
"exec_break");
(void)new TDEAction(i18n("&Kill"), 0, m_debugger,
TQ_SLOT(programKill()), actionCollection(),
"exec_kill");
(void)new TDEAction(i18n("Re&start"), 0, m_debugger,
TQ_SLOT(programRunAgain()), actionCollection(),
"exec_restart");
(void)new TDEAction(i18n("A&ttach..."), 0, this,
TQ_SLOT(slotExecAttach()), actionCollection(),
"exec_attach");
(void)new TDEAction(i18n("&Arguments..."), 0, this,
TQ_SLOT(slotExecArgs()), actionCollection(),
"exec_arguments");
// breakpoint menu
(void)new TDEAction(i18n("Set/Clear &breakpoint"), "brkpt", Key_F9,
m_filesWindow, TQ_SLOT(slotBrkptSet()), actionCollection(),
"breakpoint_set");
(void)new TDEAction(i18n("Set &temporary breakpoint"), SHIFT+Key_F9,
m_filesWindow, TQ_SLOT(slotBrkptSetTemp()), actionCollection(),
"breakpoint_set_temporary");
(void)new TDEAction(i18n("&Enable/Disable breakpoint"), CTRL+Key_F9,
m_filesWindow, TQ_SLOT(slotBrkptEnable()), actionCollection(),
"breakpoint_enable");
// only in popup menus
(void)new TDEAction(i18n("Watch Expression"), 0, this,
TQ_SLOT(slotLocalsToWatch()), actionCollection(),
"watch_expression");
(void)new TDEAction(i18n("Edit Value"), Key_F2, this,
TQ_SLOT(slotEditValue()), actionCollection(),
"edit_value");
// all actions force an UI update
TQValueList<TDEAction*> actions = actionCollection()->actions();
TQValueList<TDEAction*>::Iterator it = actions.begin();
for (; it != actions.end(); ++it) {
connect(*it, TQ_SIGNAL(activated()), this, TQ_SLOT(updateUI()));
}
createGUI("kdbgui.rc");
}
void DebuggerMainWnd::initToolbar()
{
TDEToolBar* toolbar = toolBar("mainToolBar");
toolbar->insertAnimatedWidget(ID_STATUS_BUSY,
actionCollection()->action("exec_break"), TQ_SLOT(activate()),
"pulse", -1);
toolbar->alignItemRight(ID_STATUS_BUSY, true);
m_animRunning = false;
KStatusBar* statusbar = statusBar();
statusbar->insertItem(m_statusActive, ID_STATUS_ACTIVE);
m_lastActiveStatusText = m_statusActive;
statusbar->insertItem("", ID_STATUS_MSG); /* message pane */
// reserve some translations
i18n("Restart");
i18n("Core dump");
}
bool DebuggerMainWnd::queryClose()
{
if (m_debugger != 0) {
m_debugger->shutdown();
}
return true;
}
// instance properties
void DebuggerMainWnd::saveProperties(TDEConfig* config)
{
// session management
TQString executable = "";
if (m_debugger != 0) {
executable = m_debugger->executable();
}
config->writeEntry("executable", executable);
}
void DebuggerMainWnd::readProperties(TDEConfig* config)
{
// session management
TQString execName = config->readEntry("executable");
TRACE("readProperties: executable=" + execName);
if (!execName.isEmpty()) {
debugProgram(execName, "");
}
}
const char WindowGroup[] = "Windows";
const char RecentExecutables[] = "RecentExecutables";
const char LastSession[] = "LastSession";
void DebuggerMainWnd::saveSettings(TDEConfig* config)
{
TDEConfigGroupSaver g(config, WindowGroup);
writeDockConfig(config);
fixDockConfig(config, false); // downgrade
m_recentExecAction->saveEntries(config, RecentExecutables);
TDEConfigGroupSaver g2(config, LastSession);
config->writeEntry("Width0Locals", m_localVariables->columnWidth(0));
config->writeEntry("Width0Watches", m_watches->columnWidth(0));
DebuggerMainWndBase::saveSettings(config);
}
void DebuggerMainWnd::restoreSettings(TDEConfig* config)
{
TDEConfigGroupSaver g(config, WindowGroup);
fixDockConfig(config, true); // upgrade
readDockConfig(config);
// Workaround bug #87787: KDockManager stores the titles of the KDockWidgets
// in the config files, although they are localized:
// If the user changes the language, the titles remain in the previous language.
struct { TQString text; TQWidget* w; } dw[] = {
{ i18n("Stack"), m_btWindow },
{ i18n("Locals"), m_localVariables },
{ i18n("Watches"), m_watches },
{ i18n("Registers"), m_registers },
{ i18n("Breakpoints"), m_bpTable },
{ i18n("Threads"), m_threads },
{ i18n("Output"), m_ttyWindow },
{ i18n("Memory"), m_memoryWindow }
};
for (int i = 0; i < int(sizeof(dw)/sizeof(dw[0])); i++)
{
KDockWidget* w = dockParent(dw[i].w);
w->setTabPageLabel(dw[i].text);
// this actually changes the captions in the tabs:
TQEvent ev(TQEvent::CaptionChange);
w->event(&ev);
}
m_recentExecAction->loadEntries(config, RecentExecutables);
TDEConfigGroupSaver g2(config, LastSession);
int w;
w = config->readNumEntry("Width0Locals", -1);
if (w >= 0 && w < 30000)
m_localVariables->setColumnWidth(0, w);
w = config->readNumEntry("Width0Watches", -1);
if (w >= 0 && w < 30000)
m_watches->setColumnWidth(0, w);
DebuggerMainWndBase::restoreSettings(config);
emit setTabWidth(m_tabWidth);
}
void DebuggerMainWnd::updateUI()
{
TDEToggleAction* viewFind =
static_cast<TDEToggleAction*>(actionCollection()->action("view_find"));
viewFind->setChecked(m_filesWindow->m_findDlg.isVisible());
viewFind->setEnabled(m_filesWindow->hasWindows());
actionCollection()->action("breakpoint_set")->setEnabled(m_debugger->canChangeBreakpoints());
actionCollection()->action("breakpoint_set_temporary")->setEnabled(m_debugger->canChangeBreakpoints());
actionCollection()->action("breakpoint_enable")->setEnabled(m_debugger->canChangeBreakpoints());
dockUpdateHelper("view_breakpoints", m_bpTable);
dockUpdateHelper("view_stack", m_btWindow);
dockUpdateHelper("view_locals", m_localVariables);
dockUpdateHelper("view_watched_expressions", m_watches);
dockUpdateHelper("view_registers", m_registers);
dockUpdateHelper("view_threads", m_threads);
dockUpdateHelper("view_memory", m_memoryWindow);
dockUpdateHelper("view_output", m_ttyWindow);
// AB: maybe in mainwndbase.cpp?
actionCollection()->action("file_executable")->setEnabled(m_debugger->isIdle());
actionCollection()->action("settings_program")->setEnabled(m_debugger->haveExecutable());
actionCollection()->action("file_core_dump")->setEnabled(m_debugger->canStart());
actionCollection()->action("file_close")->setEnabled(m_filesWindow->hasWindows());
actionCollection()->action("file_reload")->setEnabled(m_filesWindow->hasWindows());
actionCollection()->action("exec_step_into")->setEnabled(m_debugger->canSingleStep());
actionCollection()->action("exec_step_into_by_insn")->setEnabled(m_debugger->canSingleStep());
actionCollection()->action("exec_step_over")->setEnabled(m_debugger->canSingleStep());
actionCollection()->action("exec_step_over_by_insn")->setEnabled(m_debugger->canSingleStep());
actionCollection()->action("exec_step_out")->setEnabled(m_debugger->canSingleStep());
actionCollection()->action("exec_run_to_cursor")->setEnabled(m_debugger->canSingleStep());
actionCollection()->action("exec_movepc")->setEnabled(m_debugger->canSingleStep());
actionCollection()->action("exec_restart")->setEnabled(m_debugger->canSingleStep());
actionCollection()->action("exec_attach")->setEnabled(m_debugger->isReady());
actionCollection()->action("exec_run")->setEnabled(m_debugger->canStart() || m_debugger->canSingleStep());
actionCollection()->action("exec_kill")->setEnabled(m_debugger->haveExecutable() && m_debugger->isProgramActive());
actionCollection()->action("exec_break")->setEnabled(m_debugger->isProgramRunning());
actionCollection()->action("exec_arguments")->setEnabled(m_debugger->haveExecutable());
actionCollection()->action("edit_value")->setEnabled(m_debugger->canSingleStep());
// animation
KAnimWidget* w = toolBar("mainToolBar")->animatedWidget(ID_STATUS_BUSY);
if (m_debugger->isIdle()) {
if (m_animRunning) {
w->stop();
m_animRunning = false;
}
} else {
if (!m_animRunning) {
w->start();
m_animRunning = true;
}
}
// update statusbar
TQString newStatus;
if (m_debugger->isProgramActive())
newStatus = m_statusActive;
if (newStatus != m_lastActiveStatusText) {
statusBar()->changeItem(newStatus, ID_STATUS_ACTIVE);
m_lastActiveStatusText = newStatus;
}
}
void DebuggerMainWnd::dockUpdateHelper(TQString action, TQWidget* w)
{
TDEToggleAction* item =
static_cast<TDEToggleAction*>(actionCollection()->action(action.latin1()));
bool canChange = canChangeDockVisibility(w);
item->setEnabled(canChange);
item->setChecked(canChange && isDockVisible(w));
}
void DebuggerMainWnd::updateLineItems()
{
m_filesWindow->updateLineItems(m_debugger);
}
void DebuggerMainWnd::slotAddWatch()
{
if (m_debugger != 0) {
TQString t = m_watches->watchText();
m_debugger->addWatch(t);
}
}
void DebuggerMainWnd::slotAddWatch(const TQString& text)
{
if (m_debugger != 0) {
m_debugger->addWatch(text);
}
}
void DebuggerMainWnd::slotNewFileLoaded()
{
// updates program counter in the new file
if (m_debugger != 0)
m_filesWindow->updateLineItems(m_debugger);
}
KDockWidget* DebuggerMainWnd::dockParent(TQWidget* w)
{
while ((w = w->parentWidget()) != 0) {
if (w->isA("KDockWidget"))
return static_cast<KDockWidget*>(w);
}
return 0;
}
bool DebuggerMainWnd::isDockVisible(TQWidget* w)
{
KDockWidget* d = dockParent(w);
return d != 0 && d->mayBeHide();
}
bool DebuggerMainWnd::canChangeDockVisibility(TQWidget* w)
{
KDockWidget* d = dockParent(w);
return d != 0 && (d->mayBeHide() || d->mayBeShow());
}
// upgrades the entries from version 0.0.4 to 0.0.5 and back
void DebuggerMainWnd::fixDockConfig(TDEConfig* c, bool upgrade)
{
static const char dockGroup[] = "dock_setting_default";
if (!c->hasGroup(dockGroup))
return;
static const char oldVersion[] = "0.0.4";
static const char newVersion[] = "0.0.5";
const char* from = upgrade ? oldVersion : newVersion;
const char* to = upgrade ? newVersion : oldVersion;
TQMap<TQString,TQString> e = c->entryMap(dockGroup);
if (e["Version"] != from)
return;
TDEConfigGroupSaver g(c, dockGroup);
c->writeEntry("Version", to);
TRACE(upgrade ? "upgrading dockconfig" : "downgrading dockconfig");
// turn all orientation entries from 0 to 1 and from 1 to 0
TQMap<TQString,TQString>::Iterator i;
for (i = e.begin(); i != e.end(); ++i)
{
if (i.key().right(12) == ":orientation") {
TRACE("upgrading " + i.key() + " old value: " + *i);
int orientation = c->readNumEntry(i.key(), -1);
if (orientation >= 0) { // paranoia
c->writeEntry(i.key(), 1 - orientation);
}
}
}
}
TTYWindow* DebuggerMainWnd::ttyWindow()
{
return m_ttyWindow;
}
bool DebuggerMainWnd::debugProgram(const TQString& exe, const TQString& lang)
{
// check the file name
TQFileInfo fi(exe);
bool success = fi.isFile();
if (!success)
{
TQString msg = i18n("`%1' is not a file or does not exist");
KMessageBox::sorry(this, msg.arg(exe));
}
else
{
success = DebuggerMainWndBase::debugProgram(fi.absFilePath(), lang, this);
}
if (success)
{
m_recentExecAction->addURL(KURL(fi.absFilePath()));
// keep the directory
m_lastDirectory = fi.dirPath(true);
m_filesWindow->setExtraDirectory(m_lastDirectory);
// set caption to basename part of executable
TQString caption = fi.fileName();
setCaption(caption);
}
else
{
m_recentExecAction->removeURL(KURL(fi.absFilePath()));
}
return success;
}
void DebuggerMainWnd::slotNewStatusMsg()
{
newStatusMsg(statusBar());
}
void DebuggerMainWnd::slotFileGlobalSettings()
{
int oldTabWidth = m_tabWidth;
doGlobalOptions(this);
if (m_tabWidth != oldTabWidth) {
emit setTabWidth(m_tabWidth);
}
}
void DebuggerMainWnd::slotDebuggerStarting()
{
DebuggerMainWndBase::slotDebuggerStarting();
}
void DebuggerMainWnd::slotToggleBreak(const TQString& fileName, int lineNo,
const DbgAddr& address, bool temp)
{
// lineNo is zero-based
if (m_debugger != 0) {
m_debugger->setBreakpoint(fileName, lineNo, address, temp);
}
}
void DebuggerMainWnd::slotEnaDisBreak(const TQString& fileName, int lineNo,
const DbgAddr& address)
{
// lineNo is zero-based
if (m_debugger != 0) {
m_debugger->enableDisableBreakpoint(fileName, lineNo, address);
}
}
TQString DebuggerMainWnd::createOutputWindow()
{
TQString tty = DebuggerMainWndBase::createOutputWindow();
if (!tty.isEmpty()) {
connect(m_outputTermProc, TQ_SIGNAL(processExited(TDEProcess*)),
TQ_SLOT(slotTermEmuExited()));
}
return tty;
}
void DebuggerMainWnd::slotTermEmuExited()
{
shutdownTermWindow();
}
void DebuggerMainWnd::slotProgramStopped()
{
// when the program stopped, move the window to the foreground
if (m_popForeground) {
// unfortunately, this requires quite some force to work :-(
KWin::raiseWindow(winId());
KWin::forceActiveWindow(winId());
}
m_backTimer.stop();
}
void DebuggerMainWnd::intoBackground()
{
if (m_popForeground) {
m_backTimer.start(m_backTimeout, true); /* single-shot */
}
}
void DebuggerMainWnd::slotBackTimer()
{
lower();
}
void DebuggerMainWnd::slotRecentExec(const KURL& url)
{
TQString exe = url.path();
debugProgram(exe, "");
}
TQString DebuggerMainWnd::makeSourceFilter()
{
TQString f;
f = m_sourceFilter + " " + m_headerFilter + i18n("|All source files\n");
f += m_sourceFilter + i18n("|Source files\n");
f += m_headerFilter + i18n("|Header files\n");
f += i18n("*|All files");
return f;
}
/*
* Pop up the context menu in the locals window
*/
void DebuggerMainWnd::slotLocalsPopup(TQListViewItem*, const TQPoint& pt)
{
TQPopupMenu* popup =
static_cast<TQPopupMenu*>(factory()->container("popup_locals", this));
if (popup == 0) {
return;
}
if (popup->isVisible()) {
popup->hide();
} else {
popup->popup(pt);
}
}
/*
* Copies the currently selected item to the watch window.
*/
void DebuggerMainWnd::slotLocalsToWatch()
{
VarTree* item = m_localVariables->selectedItem();
if (item != 0 && m_debugger != 0) {
TQString text = item->computeExpr();
m_debugger->addWatch(text);
}
}
/*
* Starts editing a value in a value display
*/
void DebuggerMainWnd::slotEditValue()
{
// does one of the value trees have the focus
TQWidget* f = kapp->focusWidget();
ExprWnd* wnd;
if (f == m_localVariables) {
wnd = m_localVariables;
} else if (f == m_watches->watchVariables()) {
wnd = m_watches->watchVariables();
} else {
return;
}
if (m_localVariables->isEditing() ||
m_watches->watchVariables()->isEditing())
{
return; /* don't edit twice */
}
VarTree* expr = wnd->currentItem();
if (expr != 0 && m_debugger != 0 && m_debugger->canSingleStep())
{
TRACE("edit value");
// determine the text to edit
TQString text = m_debugger->driver()->editableValue(expr);
wnd->editValue(expr, text);
}
}
void DebuggerMainWnd::slotFileOpen()
{
// start browsing in the active file's directory
// fall back to last used directory (executable)
TQString dir = m_lastDirectory;
TQString fileName = m_filesWindow->activeFileName();
if (!fileName.isEmpty()) {
TQFileInfo fi(fileName);
dir = fi.dirPath();
}
fileName = myGetFileName(i18n("Open"),
dir,
makeSourceFilter(), this);
if (!fileName.isEmpty())
{
TQFileInfo fi(fileName);
m_lastDirectory = fi.dirPath();
m_filesWindow->setExtraDirectory(m_lastDirectory);
m_filesWindow->activateFile(fileName);
}
}
void DebuggerMainWnd::slotFileExe()
{
if (m_debugger->isIdle())
{
// open a new executable
TQString executable = myGetFileName(i18n("Select the executable to debug"),
m_lastDirectory, 0, this);
if (executable.isEmpty())
return;
debugProgram(executable, "");
}
}
void DebuggerMainWnd::slotFileCore()
{
if (m_debugger->canStart())
{
TQString corefile = myGetFileName(i18n("Select core dump"),
m_lastDirectory, 0, this);
if (!corefile.isEmpty()) {
m_debugger->useCoreFile(corefile, false);
}
}
}
void DebuggerMainWnd::slotFileProgSettings()
{
if (m_debugger != 0) {
m_debugger->programSettings(this);
}
}
void DebuggerMainWnd::slotViewStatusbar()
{
if (statusBar()->isVisible())
statusBar()->hide();
else
statusBar()->show();
setSettingsDirty();
}
void DebuggerMainWnd::slotExecUntil()
{
if (m_debugger != 0)
{
TQString file;
int lineNo;
if (m_filesWindow->activeLine(file, lineNo))
m_debugger->runUntil(file, lineNo);
}
}
void DebuggerMainWnd::slotExecAttach()
{
#ifdef PS_COMMAND
ProcAttachPS dlg(this);
// seed filter with executable name
TQFileInfo fi = m_debugger->executable();
dlg.filterEdit->setText(fi.fileName());
#else
ProcAttach dlg(this);
dlg.setText(m_debugger->attachedPid());
#endif
if (dlg.exec()) {
m_debugger->attachProgram(dlg.text());
}
}
void DebuggerMainWnd::slotExecArgs()
{
if (m_debugger != 0) {
m_debugger->programArgs(this);
}
}
void DebuggerMainWnd::slotConfigureKeys()
{
KKeyDialog::configure(actionCollection(), this);
}
#include "dbgmainwnd.moc"