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.
tdevelop/languages/ruby/debugger/debuggerpart.cpp

786 lines
31 KiB

/***************************************************************************
* Copyright (C) 1999-2001 by John Birch *
* jbb@kdevelop.org *
* Copyright (C) 2001 by Bernd Gehrmann *
* bernd@kdevelop.org *
* *
* Adapted for ruby debugging *
* -------------------------- *
* begin : Mon Nov 1 2004 *
* copyright : (C) 2004 by Richard Dale *
* email : Richard_Dale@tipitina.demon.co.uk *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "debuggerpart.h"
#include <tqdir.h>
#include <tqvbox.h>
#include <tqwhatsthis.h>
#include <tqpopupmenu.h>
#include <tdeaction.h>
#include <kdebug.h>
#include <tdefiledialog.h>
#include <kdevgenericfactory.h>
#include <kiconloader.h>
#include <tdelocale.h>
#include <tdemainwindow.h>
#include <kstatusbar.h>
#include <tdeparts/part.h>
#include <tdetexteditor/viewcursorinterface.h>
#include <tdemessagebox.h>
#include <tdeapplication.h>
#include <dcopclient.h>
#include <tqtimer.h>
#include <kstringhandler.h>
#include <kstandarddirs.h>
#include "kdevcore.h"
#include "kdevproject.h"
#include "kdevmainwindow.h"
#include "kdevappfrontend.h"
#include "kdevpartcontroller.h"
#include "kdevdebugger.h"
#include "domutil.h"
#include "variablewidget.h"
#include "rdbbreakpointwidget.h"
#include "framestackwidget.h"
#include "processwidget.h"
#include "rdbcontroller.h"
#include "breakpoint.h"
#include "dbgpsdlg.h"
#include "dbgtoolbar.h"
#include "rdbparser.h"
#include "rdboutputwidget.h"
#include "processlinemaker.h"
#include <iostream>
#include <kdevplugininfo.h>
#include <debugger.h>
namespace RDBDebugger
{
static const KDevPluginInfo data("kdevrbdebugger");
typedef KDevGenericFactory<RubyDebuggerPart> RubyDebuggerFactory;
K_EXPORT_COMPONENT_FACTORY( libkdevrbdebugger, RubyDebuggerFactory( data ) )
RubyDebuggerPart::RubyDebuggerPart( TQObject *parent, const char *name, const TQStringList & ) :
KDevPlugin( &data, parent, name ? name : "RubyDebuggerPart" ),
controller(0)
{
// setObjId("RubyDebuggerInterface");
setInstance(RubyDebuggerFactory::instance());
setXMLFile("kdevrbdebugger.rc");
m_debugger = new Debugger( partController() );
statusBarIndicator = new TQLabel(" ", mainWindow()->statusBar());
statusBarIndicator->setFixedWidth(15);
mainWindow()->statusBar()->addWidget(statusBarIndicator, 0, true);
statusBarIndicator->show();
// Setup widgets and dbgcontroller
variableWidget = new VariableWidget( 0, "rdbVariablewidget");
// /*variableWidget*/->setEnabled(false);
variableWidget->setIcon(SmallIcon("math_brace"));
variableWidget->setCaption(i18n("Variable Tree"));
TQWhatsThis::add
(variableWidget, i18n("<b>Variable tree</b><p>"
"The variable tree allows you to see "
"the variable values as you step "
"through your program using the internal "
"debugger. Click the right mouse button on items in "
"this view to get a popup menu.\n"
"To speed up stepping through your code "
"leave the tree items closed.\n"));
mainWindow()->embedSelectView(variableWidget, i18n("Variables"), i18n("Debugger variable-view"));
// mainWindow()->setViewAvailable(variableWidget, false);
rdbBreakpointWidget = new RDBBreakpointWidget( 0, "rdbBreakpointWidget" );
rdbBreakpointWidget->setCaption(i18n("Breakpoint List"));
TQWhatsThis::add
(rdbBreakpointWidget, i18n("<b>Breakpoint list</b><p>"
"Displays a list of breakpoints with "
"their current status. Clicking on a "
"breakpoint item allows you to change "
"the breakpoint and will take you "
"to the source in the editor window."));
rdbBreakpointWidget->setIcon( SmallIcon("process-stop") );
mainWindow()->embedOutputView(rdbBreakpointWidget, i18n("Breakpoints"), i18n("Debugger breakpoints"));
framestackWidget = new FramestackWidget( 0, "rdbFramestackWidget" );
framestackWidget->setEnabled(false);
framestackWidget->setCaption(i18n("Frame Stack"));
TQWhatsThis::add
(framestackWidget, i18n("<b>Frame stack</b><p>"
"Often referred to as the \"call stack\", "
"this is a list showing what method is "
"currently active and who called each "
"method to get to this point in your "
"program. By clicking on an item you "
"can see the values in any of the "
"previous calling methods."));
framestackWidget->setIcon( SmallIcon("table") );
mainWindow()->embedOutputView(framestackWidget, i18n("Frame Stack"), i18n("Debugger method call stack"));
mainWindow()->setViewAvailable(framestackWidget, false);
rdbOutputWidget = new RDBOutputWidget( 0, "rdbOutputWidget" );
rdbOutputWidget->setEnabled(false);
rdbOutputWidget->setIcon( SmallIcon("inline_image") );
rdbOutputWidget->setCaption(i18n("RDB Output"));
TQWhatsThis::add
(rdbOutputWidget, i18n("<b>RDB output</b><p>"
"Shows all rdb commands being executed. "
"You can also issue any other rdb command while debugging."));
mainWindow()->embedOutputView(rdbOutputWidget, i18n("RDB"),
i18n("RDB output"));
mainWindow()->setViewAvailable(rdbOutputWidget, false);
// rdbBreakpointWidget -> this
connect( rdbBreakpointWidget, TQ_SIGNAL(refreshBPState(const Breakpoint&)),
this, TQ_SLOT(slotRefreshBPState(const Breakpoint&)));
connect( rdbBreakpointWidget, TQ_SIGNAL(publishBPState(const Breakpoint&)),
this, TQ_SLOT(slotRefreshBPState(const Breakpoint&)));
connect( rdbBreakpointWidget, TQ_SIGNAL(gotoSourcePosition(const TQString&, int)),
this, TQ_SLOT(slotGotoSource(const TQString&, int)) );
// Now setup the actions
TDEAction *action;
// action = new TDEAction(i18n("&Start"), "1rightarrow", CTRL+SHIFT+Key_F9,
action = new TDEAction(i18n("&Start"), "dbgrun", CTRL+SHIFT+Key_F9,
this, TQ_SLOT(slotRun()),
actionCollection(), "debug_run");
action->setToolTip( i18n("Start in debugger") );
action->setWhatsThis( i18n("<b>Start in debugger</b><p>"
"Starts the debugger with the project's main "
"executable. You may set some breakpoints "
"before this, or you can interrupt the program "
"while it is running, in order to get information "
"about variables, frame stack, and so on.") );
action = new TDEAction(i18n("Sto&p"), "process-stop", 0,
this, TQ_SLOT(slotStop()),
actionCollection(), "debug_stop");
action->setToolTip( i18n("Stop debugger") );
action->setWhatsThis(i18n("<b>Stop debugger</b><p>Kills the executable and exits the debugger."));
action = new TDEAction(i18n("Interrupt"), "media-playback-pause", 0,
this, TQ_SLOT(slotPause()),
actionCollection(), "debug_pause");
action->setToolTip( i18n("Interrupt application") );
action->setWhatsThis(i18n("<b>Interrupt application</b><p>Interrupts the debugged process or current RDB command."));
action = new TDEAction(i18n("Run to &Cursor"), "dbgrunto", 0,
this, TQ_SLOT(slotRunToCursor()),
actionCollection(), "debug_runtocursor");
action->setToolTip( i18n("Run to cursor") );
action->setWhatsThis(i18n("<b>Run to cursor</b><p>Continues execution until the cursor position is reached."));
action = new TDEAction(i18n("Step &Over"), "dbgnext", 0,
this, TQ_SLOT(slotStepOver()),
actionCollection(), "debug_stepover");
action->setToolTip( i18n("Step over the next line") );
action->setWhatsThis( i18n("<b>Step over</b><p>"
"Executes one line of source in the current source file. "
"If the source line is a call to a method the whole "
"method is executed and the app will stop at the line "
"following the method call.") );
action = new TDEAction(i18n("Step &Into"), "dbgstep", 0,
this, TQ_SLOT(slotStepInto()),
actionCollection(), "debug_stepinto");
action->setToolTip( i18n("Step into the next statement") );
action->setWhatsThis( i18n("<b>Step into</b><p>"
"Executes exactly one line of source. If the source line "
"is a call to a method then execution will stop after "
"the method has been entered.") );
action = new TDEAction(i18n("Step O&ut"), "dbgstepout", 0,
this, TQ_SLOT(slotStepOut()),
actionCollection(), "debug_stepout");
action->setToolTip( i18n("Steps out of the current method") );
action->setWhatsThis( i18n("<b>Step out</b><p>"
"Executes the application until the currently executing "
"method is completed. The debugger will then display "
"the line after the original call to that method. If "
"program execution is in the outermost frame (i.e. in "
"the topleveltoggleWatchpoint) then this operation has no effect.") );
action = new TDEAction(i18n("Toggle Breakpoint"), 0, 0,
this, TQ_SLOT(toggleBreakpoint()),
actionCollection(), "debug_toggle_breakpoint");
action->setToolTip(i18n("Toggle breakpoint"));
action->setWhatsThis(i18n("<b>Toggle breakpoint</b><p>Toggles the breakpoint at the current line in editor."));
connect( mainWindow()->main()->guiFactory(), TQ_SIGNAL(clientAdded(KXMLGUIClient*)),
this, TQ_SLOT(guiClientAdded(KXMLGUIClient*)) );
connect( partController(), TQ_SIGNAL(loadedFile(const KURL &)),
rdbBreakpointWidget, TQ_SLOT(slotRefreshBP(const KURL &)) );
connect( debugger(), TQ_SIGNAL(toggledBreakpoint(const TQString &, int)),
rdbBreakpointWidget, TQ_SLOT(slotToggleBreakpoint(const TQString &, int)) );
connect( debugger(), TQ_SIGNAL(editedBreakpoint(const TQString &, int)),
rdbBreakpointWidget, TQ_SLOT(slotEditBreakpoint(const TQString &, int)) );
connect( debugger(), TQ_SIGNAL(toggledBreakpointEnabled(const TQString &, int)),
rdbBreakpointWidget, TQ_SLOT(slotToggleBreakpointEnabled(const TQString &, int)) );
connect( core(), TQ_SIGNAL(contextMenu(TQPopupMenu *, const Context *)),
this, TQ_SLOT(contextMenu(TQPopupMenu *, const Context *)) );
connect( core(), TQ_SIGNAL(stopButtonClicked(KDevPlugin*)),
this, TQ_SLOT(slotStop(KDevPlugin*)) );
connect( core(), TQ_SIGNAL(projectClosed()),
this, TQ_SLOT(projectClosed()) );
connect( partController(), TQ_SIGNAL(activePartChanged(KParts::Part*)),
this, TQ_SLOT(slotActivePartChanged(KParts::Part*)) );
procLineMaker = new ProcessLineMaker();
connect( procLineMaker, TQ_SIGNAL(receivedStdoutLine(const TQCString&)),
appFrontend(), TQ_SLOT(insertStdoutLine(const TQCString&)) );
connect( procLineMaker, TQ_SIGNAL(receivedStderrLine(const TQCString&)),
appFrontend(), TQ_SLOT(insertStderrLine(const TQCString&)) );
connect( procLineMaker, TQ_SIGNAL(receivedPartialStdoutLine(const TQCString&)),
appFrontend(), TQ_SLOT(addPartialStdoutLine(const TQCString&)) );
connect( procLineMaker, TQ_SIGNAL(receivedPartialStderrLine(const TQCString&)),
appFrontend(), TQ_SLOT(addPartialStderrLine(const TQCString&)) );
setupController();
TQTimer::singleShot(0, this, TQ_SLOT(setupDcop()));
}
RubyDebuggerPart::~RubyDebuggerPart()
{
kapp->dcopClient()->setNotifications(false);
if (variableWidget)
mainWindow()->removeView(variableWidget);
if (rdbBreakpointWidget)
mainWindow()->removeView(rdbBreakpointWidget);
if (framestackWidget)
mainWindow()->removeView(framestackWidget);
if(rdbOutputWidget)
mainWindow()->removeView(rdbOutputWidget);
delete variableWidget;
delete rdbBreakpointWidget;
delete framestackWidget;
delete rdbOutputWidget;
delete controller;
delete floatingToolBar;
delete statusBarIndicator;
delete procLineMaker;
}
void RubyDebuggerPart::guiClientAdded( KXMLGUIClient* client )
{
// Can't change state until after XMLGUI has been loaded...
// Anyone know of a better way of doing this?
if( client == this )
stateChanged( TQString("stopped") );
}
void RubyDebuggerPart::contextMenu(TQPopupMenu *popup, const Context *context)
{
if (!context->hasType( Context::EditorContext ))
return;
const EditorContext *econtext = static_cast<const EditorContext*>(context);
m_contextIdent = econtext->currentWord();
popup->insertSeparator();
if (econtext->url().isLocalFile())
{
int id = popup->insertItem( i18n("Toggle Breakpoint"), this, TQ_SLOT(toggleBreakpoint()) );
popup->setWhatsThis(id, i18n("<b>Toggle breakpoint</b><p>Toggles breakpoint at the current line."));
}
if (!m_contextIdent.isEmpty())
{
TQString squeezed = KStringHandler::csqueeze(m_contextIdent, 30);
int id = popup->insertItem( i18n("Watch: %1").arg(squeezed), this, TQ_SLOT(contextWatch()) );
popup->setWhatsThis(id, i18n("<b>Watch</b><p>Adds an expression under the cursor to the Variables/Watch list."));
id = popup->insertItem( i18n("Inspect: %1").arg(squeezed), this, TQ_SLOT(contextRubyInspect()) );
popup->setWhatsThis(id, i18n("<b>Inspect</b><p>Evaluates an expression under the cursor."));
}
}
void RubyDebuggerPart::toggleBreakpoint()
{
KParts::ReadWritePart *rwpart
= dynamic_cast<KParts::ReadWritePart*>(partController()->activePart());
KTextEditor::ViewCursorInterface *cursorIface
= dynamic_cast<KTextEditor::ViewCursorInterface*>(partController()->activeWidget());
if (!rwpart || !cursorIface)
return;
uint line, col;
cursorIface->cursorPositionReal(&line, &col);
rdbBreakpointWidget->slotToggleBreakpoint(rwpart->url().path(), line);
}
void RubyDebuggerPart::contextWatch()
{
variableWidget->slotAddWatchExpression(m_contextIdent);
}
// Evaluates the selected text
void RubyDebuggerPart::contextRubyInspect()
{
emit rubyInspect(m_contextIdent);
}
void RubyDebuggerPart::setupController()
{
VariableTree *variableTree = variableWidget->varTree();
controller = new RDBController(variableTree, framestackWidget, *projectDom());
// this -> controller
connect( this, TQ_SIGNAL(rubyInspect(const TQString&)),
controller, TQ_SLOT(slotRubyInspect(const TQString&)));
// variableTree -> framestackWidget
connect( variableTree, TQ_SIGNAL(selectFrame(int, int)),
framestackWidget, TQ_SLOT(slotSelectFrame(int, int)));
// framestackWidget -> variableTree
connect( framestackWidget, TQ_SIGNAL(frameActive(int, int, const TQString&)),
variableTree, TQ_SLOT(slotFrameActive(int, int, const TQString&)));
// variableTree -> controller
connect( variableTree, TQ_SIGNAL(expandItem(VarItem*, const TQCString&)),
controller, TQ_SLOT(slotExpandItem(VarItem*, const TQCString&)));
connect( variableTree, TQ_SIGNAL(fetchGlobals(bool)),
controller, TQ_SLOT(slotFetchGlobals(bool)));
connect( variableTree, TQ_SIGNAL(addWatchExpression(const TQString&, bool)),
controller, TQ_SLOT(slotAddWatchExpression(const TQString&, bool)));
connect( variableTree, TQ_SIGNAL(removeWatchExpression(int)),
controller, TQ_SLOT(slotRemoveWatchExpression(int)));
// framestackWidget -> controller
connect( framestackWidget, TQ_SIGNAL(selectFrame(int,int,const TQString&)),
controller, TQ_SLOT(slotSelectFrame(int,int,const TQString&)));
// rdbBreakpointWidget -> controller
connect( rdbBreakpointWidget, TQ_SIGNAL(clearAllBreakpoints()),
controller, TQ_SLOT(slotClearAllBreakpoints()));
connect( rdbBreakpointWidget, TQ_SIGNAL(publishBPState(const Breakpoint&)),
controller, TQ_SLOT(slotBPState(const Breakpoint &)));
// rdbOutputWidget -> controller
connect( rdbOutputWidget, TQ_SIGNAL(userRDBCmd(const TQString &)),
controller, TQ_SLOT(slotUserRDBCmd(const TQString&)));
connect( rdbOutputWidget, TQ_SIGNAL(breakInto()),
controller, TQ_SLOT(slotBreakInto()));
// controller -> rdbBreakpointWidget
connect( controller, TQ_SIGNAL(acceptPendingBPs()),
rdbBreakpointWidget, TQ_SLOT(slotSetPendingBPs()));
connect( controller, TQ_SIGNAL(unableToSetBPNow(int)),
rdbBreakpointWidget, TQ_SLOT(slotUnableToSetBPNow(int)));
connect( controller, TQ_SIGNAL(rawRDBBreakpointList (char*)),
rdbBreakpointWidget, TQ_SLOT(slotParseRDBBrkptList(char*)));
connect( controller, TQ_SIGNAL(rawRDBBreakpointSet(char*, int)),
rdbBreakpointWidget, TQ_SLOT(slotParseRDBBreakpointSet(char*, int)));
// controller -> this
connect( controller, TQ_SIGNAL(dbgStatus(const TQString&, int)),
this, TQ_SLOT(slotStatus(const TQString&, int)));
connect( controller, TQ_SIGNAL(showStepInSource(const TQString&, int, const TQString&)),
this, TQ_SLOT(slotShowStep(const TQString&, int)));
// controller -> procLineMaker
connect( controller, TQ_SIGNAL(ttyStdout(const char*)),
procLineMaker, TQ_SLOT(slotReceivedStdout(const char*)));
connect( controller, TQ_SIGNAL(ttyStderr(const char*)),
procLineMaker, TQ_SLOT(slotReceivedStderr(const char*)));
// controller -> rdbOutputWidget
connect( controller, TQ_SIGNAL(rdbStdout(const char*)),
rdbOutputWidget, TQ_SLOT(slotReceivedStdout(const char*)) );
connect( controller, TQ_SIGNAL(rdbStderr(const char*)),
rdbOutputWidget, TQ_SLOT(slotReceivedStderr(const char*)) );
connect( controller, TQ_SIGNAL(dbgStatus(const TQString&, int)),
rdbOutputWidget, TQ_SLOT(slotDbgStatus(const TQString&, int)));
}
bool RubyDebuggerPart::startDebugger()
{
TQString build_dir; // Currently selected build directory
TQString run_directory; // Directory from where the program should be run
TQString program; // Absolute path to application
TQString run_arguments; // Command line arguments to be passed to the application
TQString ruby_interpreter; // Absolute path to the ruby interpreter
TQString debuggee_path; // Absolute path to debuggee.rb debugger script
bool show_constants; // Show constants in the debugger
bool trace_into_ruby; // Trace into the ruby code installed under sitedir
if (project()) {
build_dir = project()->buildDirectory();
run_directory = DomUtil::readEntry(*projectDom(), "/kdevscriptproject/run/globalcwd");
if (run_directory.isEmpty())
run_directory = project()->buildDirectory();
}
int runMainProgram = DomUtil::readIntEntry(*projectDom(), "/kdevrubysupport/run/runmainprogram");
if (runMainProgram == 0) {
program = project()->projectDirectory() + "/" + DomUtil::readEntry(*projectDom(), "/kdevrubysupport/run/mainprogram");
} else {
KParts::ReadOnlyPart *ro_part = dynamic_cast<KParts::ReadOnlyPart*>(partController()->activePart());
if (ro_part != 0) {
program = ro_part->url().path();
}
}
run_arguments = DomUtil::readEntry(*projectDom(), "/kdevrubysupport/run/programargs");
TQString shell = DomUtil::readEntry(*projectDom(), "/kdevrbdebugger/general/dbgshell");
if( !shell.isEmpty() )
{
TQFileInfo info( shell );
if( info.isRelative() )
{
shell = build_dir + "/" + shell;
info.setFile( shell );
}
if( !info.exists() )
{
KMessageBox::error(
mainWindow()->main(),
i18n("Could not locate the debugging shell '%1'.").arg( shell ),
i18n("Debugging Shell Not Found") );
return false;
}
}
core()->running(this, true);
stateChanged( TQString("active") );
TDEActionCollection *ac = actionCollection();
ac->action("debug_run")->setText( i18n("&Continue") );
// ac->action("debug_run")->setIcon( "dbgrun" );
ac->action("debug_run")->setToolTip( i18n("Continues the application execution") );
ac->action("debug_run")->setWhatsThis( i18n("Continue application execution\n\n"
"Continues the execution of your application in the "
"debugger. This only takes effect when the application "
"has been halted by the debugger (i.e. a breakpoint has "
"been activated or the interrupt was pressed).") );
// mainWindow()->setViewAvailable(variableWidget, true);
mainWindow()->setViewAvailable(framestackWidget, true);
mainWindow()->setViewAvailable(rdbOutputWidget, true);
// variableWidget->setEnabled(true);
framestackWidget->setEnabled(true);
rdbOutputWidget->clear();
rdbOutputWidget->setEnabled(true);
if (DomUtil::readBoolEntry(*projectDom(), "/kdevrbdebugger/general/floatingtoolbar", false))
{
floatingToolBar = new DbgToolBar(this, mainWindow()->main());
floatingToolBar->show();
}
ruby_interpreter = DomUtil::readEntry(*projectDom(), "/kdevrubysupport/run/interpreter");
int coding = DomUtil::readIntEntry(*projectDom(), "/kdevrubysupport/run/charactercoding");
TQString character_coding("-K");
switch (coding) {
case 0:
character_coding.append("A");
break;
case 1:
character_coding.append("E");
break;
case 2:
character_coding.append("S");
break;
case 3:
character_coding.append("U");
break;
}
// ruby_interpreter.append(TQString(" -K") + code);
debuggee_path = ::locate("data", "kdevrbdebugger/debuggee.rb", instance());
show_constants = DomUtil::readBoolEntry(*projectDom(), "/kdevrbdebugger/general/showconstants");
trace_into_ruby = DomUtil::readBoolEntry(*projectDom(), "/kdevrbdebugger/general/traceintoruby");
controller->slotStart(ruby_interpreter, character_coding, run_directory, debuggee_path, program, run_arguments, show_constants, trace_into_ruby);
return true;
}
void RubyDebuggerPart::slotStopDebugger()
{
controller->slotStopDebugger();
debugger()->clearExecutionPoint();
delete floatingToolBar;
floatingToolBar = 0;
rdbBreakpointWidget->reset();
framestackWidget->clear();
variableWidget->varTree()->clear();
// variableWidget->setEnabled(false);
framestackWidget->setEnabled(false);
rdbOutputWidget->setEnabled(false);
// mainWindow()->setViewAvailable(variableWidget, false);
mainWindow()->setViewAvailable(framestackWidget, false);
mainWindow()->setViewAvailable(rdbOutputWidget, false);
TDEActionCollection *ac = actionCollection();
ac->action("debug_run")->setText( i18n("&Start") );
// ac->action("debug_run")->setIcon( "1rightarrow" );
ac->action("debug_run")->setToolTip( i18n("Runs the program in the debugger") );
ac->action("debug_run")->setWhatsThis( i18n("Start in debugger\n\n"
"Starts the debugger with the project's main "
"executable. You may set some breakpoints "
"before this, or you can interrupt the program "
"while it is running, in order to get information "
"about variables, frame stack, and so on.") );
stateChanged( TQString("stopped") );
core()->running(this, false);
}
void RubyDebuggerPart::projectClosed()
{
slotStopDebugger();
}
void RubyDebuggerPart::slotRun()
{
if (controller->stateIsOn(s_programExited)) {
rdbBreakpointWidget->reset();
}
if ( controller->stateIsOn( s_dbgNotStarted ) ) {
mainWindow()->statusBar()->message(i18n("Debugging program"), 1000);
mainWindow()->raiseView(rdbOutputWidget);
appFrontend()->clearView();
startDebugger();
} else {
TDEActionCollection *ac = actionCollection();
ac->action("debug_run")->setText( i18n("&Continue") );
ac->action("debug_run")->setToolTip( i18n("Continues the application execution") );
ac->action("debug_run")->setWhatsThis( i18n("Continue application execution\n\n"
"Continues the execution of your application in the "
"debugger. This only takes effect when the application "
"has been halted by the debugger (i.e. a breakpoint has "
"been activated or the interrupt was pressed).") );
mainWindow()->statusBar()->message(i18n("Continuing program"), 1000);
}
controller->slotRun();
}
void RubyDebuggerPart::slotStop(KDevPlugin* which)
{
if( which != 0 && which != this )
return;
// if( !controller->stateIsOn( s_dbgNotStarted ) && !controller->stateIsOn( s_shuttingDown ) )
slotStopDebugger();
}
void RubyDebuggerPart::slotPause()
{
controller->slotBreakInto();
}
void RubyDebuggerPart::slotRunToCursor()
{
KParts::ReadWritePart *rwpart
= dynamic_cast<KParts::ReadWritePart*>(partController()->activePart());
KTextEditor::ViewCursorInterface *cursorIface
= dynamic_cast<KTextEditor::ViewCursorInterface*>(partController()->activeWidget());
if (!rwpart || !rwpart->url().isLocalFile() || !cursorIface)
return;
uint line, col;
cursorIface->cursorPosition(&line, &col);
controller->slotRunUntil(rwpart->url().path(), line);
}
void RubyDebuggerPart::slotStepOver()
{
controller->slotStepOver();
}
void RubyDebuggerPart::slotStepInto()
{
controller->slotStepInto();
}
void RubyDebuggerPart::slotStepOut()
{
controller->slotStepOutOff();
}
void RubyDebuggerPart::slotRefreshBPState( const Breakpoint& BP)
{
if (BP.type() == BP_TYPE_FilePos)
{
const FilePosBreakpoint& bp = dynamic_cast<const FilePosBreakpoint&>(BP);
if (bp.isActionDie())
debugger()->setBreakpoint(bp.fileName(), bp.lineNum()-1, -1, true, false);
else
debugger()->setBreakpoint(bp.fileName(), bp.lineNum()-1,
1/*bp->id()*/, bp.isEnabled(), bp.isPending() );
}
}
void RubyDebuggerPart::slotStatus(const TQString &msg, int state)
{
TQString stateIndicator;
if (state & s_dbgNotStarted)
{
stateIndicator = " ";
}
else if (state & s_appBusy)
{
stateIndicator = "A";
debugger()->clearExecutionPoint();
stateChanged( TQString("active") );
}
else if (state & s_programExited)
{
stateIndicator = "E";
stateChanged( TQString("stopped") );
TDEActionCollection *ac = actionCollection();
ac->action("debug_run")->setText( i18n("Restart") );
// ac->action("debug_run")->setIcon( "1rightarrow" );
ac->action("debug_run")->setToolTip( i18n("Restart the program in the debugger") );
ac->action("debug_run")->setWhatsThis( i18n("Restart in debugger\n\n"
"Restarts the program in the debugger") );
// slotStop();
}
else
{
stateIndicator = "P";
stateChanged( TQString("paused") );
}
// And now? :-)
kdDebug(9012) << "Debugger state: " << stateIndicator << ": " << endl;
kdDebug(9012) << " " << msg << endl;
statusBarIndicator->setText(stateIndicator);
if (!msg.isEmpty())
mainWindow()->statusBar()->message(msg, 3000);
}
void RubyDebuggerPart::slotShowStep(const TQString &fileName, int lineNum)
{
if ( ! fileName.isEmpty() )
{
// Debugger counts lines from 1
debugger()->gotoExecutionPoint(KURL( fileName ), lineNum-1);
}
}
void RubyDebuggerPart::slotGotoSource(const TQString &fileName, int lineNum)
{
if ( ! fileName.isEmpty() )
partController()->editDocument(KURL( fileName ), lineNum);
}
void RubyDebuggerPart::slotActivePartChanged( KParts::Part* part )
{
TDEAction* action = actionCollection()->action("debug_toggle_breakpoint");
if(!action)
return;
if(!part)
{
action->setEnabled(false);
return;
}
KTextEditor::ViewCursorInterface *iface
= dynamic_cast<KTextEditor::ViewCursorInterface*>(part->widget());
action->setEnabled( iface != 0 );
}
void RubyDebuggerPart::restorePartialProjectSession(const TQDomElement* el)
{
rdbBreakpointWidget->restorePartialProjectSession(el);
variableWidget->restorePartialProjectSession(el);
}
void RubyDebuggerPart::savePartialProjectSession(TQDomElement* el)
{
rdbBreakpointWidget->savePartialProjectSession(el);
variableWidget->savePartialProjectSession(el);
}
}
KDevAppFrontend * RDBDebugger::RubyDebuggerPart::appFrontend( )
{
return extension<KDevAppFrontend>("TDevelop/AppFrontend");
}
KDevDebugger * RDBDebugger::RubyDebuggerPart::debugger()
{
return m_debugger;
}
#include "debuggerpart.moc"