# -*- coding: utf-8 -*-
# Copyright (c) 2002, 2003 Detlev Offenbach <detlev@die-offenbachs.de>
#
"""
Module implementing the debugger UI.
"""
import os
from qt import *
from DebugIcons import *
from UI.Info import *
from VariablesFilterDialog import *
from ExceptionsFilterDialog import *
from BreakpointDialog import *
from StartDialog import *
import Preferences
import Utilities
class DebugUI(QObject):
"""
Class implementing the debugger part of the UI.
"""
def __init__(self,ui,vm,dbs,sbv):
"""
Constructor
Arguments
ui -- reference to the main UI
vm -- reference to the viewmanager
dbs -- reference to the debug server
sbv -- reference to the shell/browser/variables/exception widget
Signals
clientStack -- emitted at breaking after a reported exception
"""
QObject.__init__(self, ui)
self.ui = ui
self.viewmanager = vm
self.dbs = dbs
self.sbv = sbv
# Clear some variables
self.projectOpen = 0
self.editorOpen = 0
self.excList = []
# Generate the variables filter dialog
self.dbgFilterDialog = VariablesFilterDialog(self.ui, 'Filter Dialog', 1)
self.argvHistory = QStringList()
self.wdHistory = QStringList()
self.exceptions = 1
self.evalHistory = QStringList()
self.execHistory = QStringList()
self.lastDebuggedFile = None
self.lastStartAction = 0 # 0=None, 1=Script, 2=Project
self.lastAction = -1
self.actions = [self.handleContinue, self.handleStep,\
self.handleStepOver, self.handleStepOut,\
self.handleStepQuit]
self.localsVarFilter, self.globalsVarFilter = Preferences.getVarFilters()
self.sbv.setLocalVariablesFilter(self.localsVarFilter)
# Connect the signals emitted by the debug-server
self.connect(dbs,PYSIGNAL('clientGone'),self.handleClientGone)
self.connect(dbs,PYSIGNAL('clientLine'),self.handleLineChange)
self.connect(dbs,PYSIGNAL('clientExit'),self.handleExit)
self.connect(dbs,PYSIGNAL('clientSyntaxError'),self.handleSyntaxError)
self.connect(dbs,PYSIGNAL('clientException'),self.handleException)
self.connect(dbs,PYSIGNAL('clientVariables'),self.handleClientVariables)
self.connect(dbs,PYSIGNAL('passiveDebugStarted'),self.handlePassiveDebugStarted)
self.connect(dbs,PYSIGNAL('clientRawInput'),sbv.handleRawInput)
self.connect(dbs,PYSIGNAL('clientRawInputSent'),sbv.restoreCurrentPage)
# Connect the signals emitted by the viewmanager
self.connect(vm,PYSIGNAL('editorOpened'),self.handleEditorOpened)
self.connect(vm,PYSIGNAL('lastEditorClosed'),self.handleLastEditorClosed)
# Connect the signals emitted by the project
project = ui.getProject()
self.connect(project,PYSIGNAL('projectOpened'),self.handleProjectOpened)
self.connect(project,PYSIGNAL('newProject'),self.handleProjectOpened)
self.connect(project,PYSIGNAL('projectClosed'),self.handleProjectClosed)
self.connect(project,PYSIGNAL('projectSessionLoaded'),self.handleProjectSessionLoaded)
# Set a flag for the passive debug mode
self.passive = Preferences.getDebugger("PassiveDbgEnabled")
def initActions(self):
"""
Method defining the user interface actions.
"""
self.runAct = QAction(self.trUtf8('Run Script'),
QIconSet(IconRunScript),
self.trUtf8('&Run Script...'),Qt.Key_F2,self)
self.runAct.setStatusTip(self.trUtf8('Run the current Script'))
self.runAct.setWhatsThis(self.trUtf8(
"""<b>Run Script</b>"""
"""<p>Set the command line arguments and run the script outside the debugger."""
""" If the file has unsaved changes it may be saved first.</p>"""
))
self.connect(self.runAct,SIGNAL('activated()'),self.handleRunScript)
self.runProjectAct = QAction(self.trUtf8('Run Project'),
QIconSet(IconRunProject),
self.trUtf8('Run &Project...'),Qt.SHIFT + Qt.Key_F2,self)
self.runProjectAct.setStatusTip(self.trUtf8('Run the current Project'))
self.runProjectAct.setWhatsThis(self.trUtf8(
"""<b>Run Project</b>"""
"""<p>Set the command line arguments and run the current project"""
""" outside the debugger."""
""" If files of the current project have unsaved changes they may"""
""" be saved first.</p>"""
))
self.connect(self.runProjectAct,SIGNAL('activated()'),self.handleRunProject)
self.coverageAct = QAction(self.trUtf8('Coverage run of Script'),
QIconSet(IconCoverageScript),
self.trUtf8('Coverage run of Script...'),0,self)
self.coverageAct.setStatusTip(self.trUtf8('Perform a coverage run of the current Script'))
self.coverageAct.setWhatsThis(self.trUtf8(
"""<b>Coverage run of Script</b>"""
"""<p>Set the command line arguments and run the script under the control of a"""
""" coverage analysis tool. If the file has unsaved changes it may be"""
""" saved first.</p>"""
))
self.connect(self.coverageAct,SIGNAL('activated()'),self.handleCoverageScript)
self.coverageProjectAct = QAction(self.trUtf8('Coverage run of Project'),
QIconSet(IconCoverageProject),
self.trUtf8('Coverage run of Project...'),0,self)
self.coverageProjectAct.setStatusTip(self.trUtf8('Perform a coverage run of the current Project'))
self.coverageProjectAct.setWhatsThis(self.trUtf8(
"""<b>Coverage run of Project</b>"""
"""<p>Set the command line arguments and run the current project"""
""" under the control of a coverage analysis tool."""
""" If files of the current project have unsaved changes they may"""
""" be saved first.</p>"""
))
self.connect(self.coverageProjectAct,SIGNAL('activated()'),self.handleCoverageProject)
self.profileAct = QAction(self.trUtf8('Profile Script'),
QIconSet(IconProfileScript),
self.trUtf8('Profile Script...'),0,self)
self.profileAct.setStatusTip(self.trUtf8('Profile the current Script'))
self.profileAct.setWhatsThis(self.trUtf8(
"""<b>Profile Script</b>"""
"""<p>Set the command line arguments and profile the script."""
""" If the file has unsaved changes it may be saved first.</p>"""
))
self.connect(self.profileAct,SIGNAL('activated()'),self.handleProfileScript)
self.profileProjectAct = QAction(self.trUtf8('Profile Project'),
QIconSet(IconProfileProject),
self.trUtf8('Profile Project...'),0,self)
self.profileProjectAct.setStatusTip(self.trUtf8('Profile the current Project'))
self.profileProjectAct.setWhatsThis(self.trUtf8(
"""<b>Profile Project</b>"""
"""<p>Set the command line arguments and profile the current project."""
""" If files of the current project have unsaved changes they may"""
""" be saved first.</p>"""
))
self.connect(self.profileProjectAct,SIGNAL('activated()'),self.handleProfileProject)
self.debugAct = QAction(self.trUtf8('Debug Script'),
QIconSet(IconDebugScript),
self.trUtf8('&Debug Script...'),Qt.Key_F5,self)
self.debugAct.setStatusTip(self.trUtf8('Debug the current Script'))
self.debugAct.setWhatsThis(self.trUtf8(
"""<b>Debug Script</b>"""
"""<p>Set the command line arguments and set the current line to be the first"""
""" executable Python statement of the current editor window."""
""" If the file has unsaved changes it may be saved first.</p>"""
))
self.connect(self.debugAct,SIGNAL('activated()'),self.handleDebugScript)
self.debugProjectAct = QAction(self.trUtf8('Debug Project'),
QIconSet(IconDebugProject),
self.trUtf8('Debug &Project...'),Qt.SHIFT + Qt.Key_F5,self)
self.debugProjectAct.setStatusTip(self.trUtf8('Debug the current Project'))
self.debugProjectAct.setWhatsThis(self.trUtf8(
"""<b>Debug Project</b>"""
"""<p>Set the command line arguments and set the current line to be the first"""
""" executable Python statement of the main script of the current project."""
""" If files of the current project have unsaved changes they may"""
""" be saved first.</p>"""
))
self.connect(self.debugProjectAct,SIGNAL('activated()'),self.handleDebugProject)
self.restartAct = QAction(self.trUtf8('Restart Script'),
QIconSet(IconRestart),
self.trUtf8('Restart Script...'),Qt.Key_F4,self)
self.restartAct.setStatusTip(self.trUtf8('Restart the last debugged script'))
self.restartAct.setWhatsThis(self.trUtf8(
"""<b>Restart Script</b>"""
"""<p>Set the command line arguments and set the current line to be the first"""
""" executable Python statement of the script that was debugged last."""
""" If there are unsaved changes, they may be saved first.</p>"""
))
self.connect(self.restartAct,SIGNAL('activated()'),self.handleRestart)
self.debugActGrp = QActionGroup(self)
act = QAction(self.trUtf8('Continue'),
QIconSet(IconContinue),
self.trUtf8('&Continue'),Qt.Key_F6,
self.debugActGrp)
act.setStatusTip(self.trUtf8('Continue running the program from the current line'))
act.setWhatsThis(self.trUtf8(
"""<b>Continue</b>"""
"""<p>Continue running the program from the current line. The program will"""
""" stop when it terminates or when a breakpoint is reached.</p>"""
))
self.connect(act,SIGNAL('activated()'),self.handleContinue)
act = QAction(self.trUtf8('Single Step'),
QIconSet(IconStep),
self.trUtf8('Sin&gle Step'),Qt.Key_F7,
self.debugActGrp)
act.setStatusTip(self.trUtf8('Execute a single Python statement'))
act.setWhatsThis(self.trUtf8(
"""<b>Single Step</b>"""
"""<p>Execute a single Python statement. If the statement"""
""" is an <tt>import</tt> statement, a class constructor, or a"""
""" method or function call then control is returned to the debugger at"""
""" the next statement.</p>"""
))
self.connect(act,SIGNAL('activated()'),self.handleStep)
act = QAction(self.trUtf8('Step Over'),
QIconSet(IconStepOver),
self.trUtf8('Step &Over'),Qt.Key_F8,
self.debugActGrp)
act.setStatusTip(self.trUtf8('Execute a single Python statement staying in the current frame'))
act.setWhatsThis(self.trUtf8(
"""<b>Step Over</b>"""
"""<p>Execute a single Python statement staying in the same frame. If"""
""" the statement is an <tt>import</tt> statement, a class constructor, or a"""
""" method or function call then control is returned to the debugger after"""
""" the statement has completed.</p>"""
))
self.connect(act,SIGNAL('activated()'),self.handleStepOver)
act = QAction(self.trUtf8('Step Out'),
QIconSet(IconStepOut),
self.trUtf8('Step Ou&t'),Qt.Key_F9,
self.debugActGrp)
act.setStatusTip(self.trUtf8('Execute Python statements until leaving the current frame'))
act.setWhatsThis(self.trUtf8(
"""<b>Step Out</b>"""
"""<p>Execute Python statements until leaving the current frame. If"""
""" the statements are inside an <tt>import</tt> statement, a class constructor, or a"""
""" method or function call then control is returned to the debugger after"""
""" the current frame has been left.</p>"""
))
self.connect(act,SIGNAL('activated()'),self.handleStepOut)
act = QAction(self.trUtf8('Stop'),
QIconSet(IconStepQuit),
self.trUtf8('&Stop'),Qt.Key_F10,
self.debugActGrp)
act.setStatusTip(self.trUtf8('Stop debugging'))
act.setWhatsThis(self.trUtf8(
"""<b>Stop</b>"""
"""<p>Stop the running debugging session.</p>"""
))
self.connect(act,SIGNAL('activated()'),self.handleStepQuit)
self.debugActGrp2 = QActionGroup(self)
act = QAction(self.trUtf8('Evaluate'),
self.trUtf8('E&valuate...'),
0,self.debugActGrp2)
act.setStatusTip(self.trUtf8('Evaluate in current context'))
act.setWhatsThis(self.trUtf8(
"""<b>Evaluate</b>"""
"""<p>Evaluate an expresion in the current context of the"""
""" debugged program. The result is displayed in the"""
""" shell window.</p>"""
))
self.connect(act,SIGNAL('activated()'),self.handleEval)
act = QAction(self.trUtf8('Execute'),
self.trUtf8('E&xecute...'),
0,self.debugActGrp2)
act.setStatusTip(self.trUtf8('Execute a one line statement in the current context'))
act.setWhatsThis(self.trUtf8(
"""<b>Execute</b>"""
"""<p>Execute a one line statement in the current context"""
""" of the debugged program.</p>"""
))
self.connect(act,SIGNAL('activated()'),self.handleExec)
self.dbgFilterAct = QAction(self.trUtf8('Variables Filter'),
self.trUtf8('Varia&bles Filter...'), 0, self)
self.dbgFilterAct.setStatusTip(self.trUtf8('Configure variables filter'))
self.dbgFilterAct.setWhatsThis(self.trUtf8(
"""<b>Variables Filter</b>"""
"""<p>Configure the variables filter. Only variable types that are not"""
""" selected are displayed in the global or local variables window"""
""" during a debugging session.</p>"""
))
self.connect(self.dbgFilterAct,SIGNAL('activated()'), self.handleConfigFilters)
self.excFilterAct = QAction(self.trUtf8('Exceptions Filter'),
self.trUtf8('&Exceptions Filter...'), 0, self)
self.excFilterAct.setStatusTip(self.trUtf8('Configure exceptions filter'))
self.excFilterAct.setWhatsThis(self.trUtf8(
"""<b>Exceptions Filter</b>"""
"""<p>Configure the exceptions filter. Only exception types that are"""
""" listed are highlighted during a debugging session.</p>"""
"""<p>Please note, that all unhandled exceptions are highlighted"""
""" indepent from the filter list.</p>"""
))
self.connect(self.excFilterAct,SIGNAL('activated()'), self.handleExceptionsFilter)
self.dbgSetBpActGrp = QActionGroup(self)
act = QAction(self.trUtf8('Set/Reset Breakpoint'),
self.trUtf8('Set/Reset Breakpoint'), Qt.Key_F11,
self.dbgSetBpActGrp)
act.setStatusTip(self.trUtf8('Set/Reset Breakpoint'))
act.setWhatsThis(self.trUtf8(
"""<b>Set/Reset Breakpoint</b>"""
"""<p>Sets or resets a breakpoint at the current line of the"""
""" current editor.</p>"""
))
self.connect(act,SIGNAL('activated()'), self.handleToggleBreakpoint)
act = QAction(self.trUtf8('Set/Change Conditional Breakpoint'),
self.trUtf8('Set/Change Conditional Breakpoint'), Qt.Key_F12,
self.dbgSetBpActGrp)
act.setStatusTip(self.trUtf8('Set/Change Conditional Breakpoint'))
act.setWhatsThis(self.trUtf8(
"""<b>Set/Change Conditional Breakpoint</b>"""
"""<p>Sets a conditional breakpoint or changes the breakpoints"""
""" condition. It works at the current line of the current editor.</p>"""
))
self.connect(act,SIGNAL('activated()'), self.handleToggleCBreakpoint)
self.dbgAllBpActGrp = QActionGroup(self)
act = QAction(self.trUtf8('File Breakpoints'),
self.trUtf8('&File Breakpoints...'), 0, self.dbgAllBpActGrp)
act.setStatusTip(self.trUtf8('Show breakpoints of the current file'))
act.setWhatsThis(self.trUtf8(
"""<b>File Breakpoints</b>"""
"""<p>Show all breakpoints of the current file. The dialog allows to"""
""" delete or change these breakpoints.</p>"""
))
self.connect(act,SIGNAL('activated()'), self.handleAllFileBp)
act = QAction(self.trUtf8('All Breakpoints'),
self.trUtf8('&All Breakpoints...'), 0, self.dbgAllBpActGrp)
act.setStatusTip(self.trUtf8('Show all breakpoints'))
act.setWhatsThis(self.trUtf8(
"""<b>All Breakpoints</b>"""
"""<p>Show all breakpoints. The dialog allows to"""
""" delete or change these breakpoints.</p>"""
))
self.connect(act,SIGNAL('activated()'), self.handleAllBp)
self.dbgProjectBpAct = QAction(self.trUtf8('Project Breakpoints'),
self.trUtf8('Pro&ject Breakpoints...'), 0, self)
self.dbgProjectBpAct.setStatusTip(self.trUtf8('Show the projects breakpoints'))
self.dbgProjectBpAct.setWhatsThis(self.trUtf8(
"""<b>Project Breakpoints</b>"""
"""<p>Show all breakpoints of the current project. The dialog allows to"""
""" delete or change these breakpoints.</p>"""
))
self.connect(self.dbgProjectBpAct,SIGNAL('activated()'), self.handleProjectBp)
self.debugActGrp.setEnabled(0)
self.debugActGrp2.setEnabled(0)
self.dbgSetBpActGrp.setEnabled(0)
self.dbgAllBpActGrp.setEnabled(0)
self.dbgProjectBpAct.setEnabled(0)
self.runAct.setEnabled(0)
self.runProjectAct.setEnabled(0)
self.profileAct.setEnabled(0)
self.profileProjectAct.setEnabled(0)
self.coverageAct.setEnabled(0)
self.coverageProjectAct.setEnabled(0)
self.debugAct.setEnabled(0)
self.debugProjectAct.setEnabled(0)
self.restartAct.setEnabled(0)
def initMenu(self):
"""
Public slot to initialize the project menu.
Returns
the generated menu
"""
menu = QPopupMenu(self.parent())
menu.insertTearOffHandle()
self.restartAct.addTo(menu)
menu.insertSeparator()
self.runAct.addTo(menu)
self.runProjectAct.addTo(menu)
menu.insertSeparator()
self.profileAct.addTo(menu)
self.profileProjectAct.addTo(menu)
menu.insertSeparator()
self.coverageAct.addTo(menu)
self.coverageProjectAct.addTo(menu)
menu.insertSeparator()
self.debugAct.addTo(menu)
self.debugProjectAct.addTo(menu)
self.debugActGrp.addTo(menu)
menu.insertSeparator()
self.debugActGrp2.addTo(menu)
menu.insertSeparator()
self.dbgSetBpActGrp.addTo(menu)
menu.insertSeparator()
self.dbgProjectBpAct.addTo(menu)
self.dbgAllBpActGrp.addTo(menu)
menu.insertSeparator()
self.dbgFilterAct.addTo(menu)
self.excFilterAct.addTo(menu)
return menu
def initToolbar(self):
"""
Public slot to initialize the project toolbar.
Returns
the generated toolbar
"""
tb = QToolBar(self.parent())
self.restartAct.addTo(tb)
tb.addSeparator()
self.runAct.addTo(tb)
self.runProjectAct.addTo(tb)
tb.addSeparator()
self.profileAct.addTo(tb)
self.profileProjectAct.addTo(tb)
tb.addSeparator()
self.coverageAct.addTo(tb)
self.coverageProjectAct.addTo(tb)
tb.addSeparator()
self.debugAct.addTo(tb)
self.debugProjectAct.addTo(tb)
self.debugActGrp.addTo(tb)
return tb
def setArgvHistory(self, argsStr):
"""
Public slot to initialize the argv History used for debugging.
Arguments
argsStr -- the commandline argumnets (string or QString)
"""
self.argvHistory.remove(argsStr)
self.argvHistory.prepend(argsStr)
def setWdHistory(self, wdStr):
"""
Public slot to initialize the wd History used for debugging.
Arguments
wdStr -- the working directory (string or QString)
"""
self.wdHistory.remove(wdStr)
self.wdHistory.prepend(wdStr)
def setExceptionReporting(self, exceptions):
"""
Public slot to initialize the exception reporting flag.
Arguments
exceptions -- flag indicating exception reporting status (boolean)
"""
self.exceptions = exceptions
def setExcList(self, excList):
"""
Public slot to initialize the exceptions type list.
Arguments
excList -- list of exception types (list of strings)
"""
self.excList = excList
def handleEditorOpened(self):
"""
Private slot to handle the editorOpened signal.
"""
if not self.passive:
self.debugAct.setEnabled(1)
self.runAct.setEnabled(1)
self.profileAct.setEnabled(1)
self.coverageAct.setEnabled(1)
self.dbgAllBpActGrp.setEnabled(1)
self.dbgSetBpActGrp.setEnabled(1)
self.editorOpen = 1
def handleLastEditorClosed(self):
"""
Private slot to handle the closeProgram signal.
"""
self.editorOpen = 0
self.debugAct.setEnabled(0)
self.runAct.setEnabled(0)
self.profileAct.setEnabled(0)
self.coverageAct.setEnabled(0)
self.debugActGrp.setEnabled(0)
self.debugActGrp2.setEnabled(0)
self.dbgAllBpActGrp.setEnabled(0)
self.dbgSetBpActGrp.setEnabled(0)
self.lastAction = -1
if not self.projectOpen:
self.restartAct.setEnabled(0)
self.lastDebuggedFile = None
self.lastStartAction = 0
def handleProjectOpened(self):
"""
Private slot to handle the projectOpened signal.
"""
self.projectOpen = 1
if not self.passive:
self.debugProjectAct.setEnabled(1)
self.runProjectAct.setEnabled(1)
self.profileProjectAct.setEnabled(1)
self.coverageProjectAct.setEnabled(1)
self.dbgProjectBpAct.setEnabled(1)
def handleProjectClosed(self):
"""
Private slot to handle the projectClosed signal.
"""
self.projectOpen = 0
self.runProjectAct.setEnabled(0)
self.profileProjectAct.setEnabled(0)
self.coverageProjectAct.setEnabled(0)
self.debugProjectAct.setEnabled(0)
self.dbgProjectBpAct.setEnabled(0)
if not self.editorOpen:
self.restartAct.setEnabled(0)
self.lastDebuggedFile = None
self.lastStartAction = 0
def handleProjectSessionLoaded(self):
"""
Private slot to handle the projectSessionLoaded signal.
"""
fn = self.ui.getProject().getMainScript(1)
if fn is not None:
self.lastStartAction = 2
self.lastDebuggedFile = fn
self.restartAct.setEnabled(1)
def shutdownServer(self):
"""
Public method to shutdown the debug server.
This is needed to cleanly close the sockets on Win OS.
Returns
always true
"""
self.dbs.shutdownServer()
return 1
def resetUI(self):
"""
Private slot to reset the user interface.
"""
self.debugActGrp.setEnabled(0)
self.debugActGrp2.setEnabled(0)
if not self.passive:
self.debugAct.setEnabled(self.editorOpen)
self.runAct.setEnabled(self.editorOpen)
self.profileAct.setEnabled(self.editorOpen)
self.coverageAct.setEnabled(self.editorOpen)
self.debugProjectAct.setEnabled(self.projectOpen)
self.runProjectAct.setEnabled(self.projectOpen)
self.profileProjectAct.setEnabled(self.projectOpen)
self.coverageProjectAct.setEnabled(self.projectOpen)
if self.lastDebuggedFile is not None and \
(self.editorOpen or self.projectOpen):
self.restartAct.setEnabled(1)
else:
self.restartAct.setEnabled(0)
self.emit(PYSIGNAL('resetUI'), ())
def handleLineChange(self,fn,line):
"""
Private method to handle a change to the current line.
Arguments
fn -- filename (string)
line -- linenumber (int)
"""
self.ui.setActiveWindow()
self.ui.raiseW()
self.viewmanager.setFileLine(fn,line)
self.getClientVariables()
def handleExit(self,status):
"""
Private method to handle the debugged program terminating.
Arguments
status -- exit code of the debugged program (int)
"""
self.viewmanager.handleExit()
self.resetUI()
QMessageBox.information(self.ui,Program,
self.trUtf8('<b>%1</b> has terminated with an exit status of %2.')
.arg(Utilities.normabspath(self.ui.currentProg))
.arg(status))
def handleSyntaxError(self,status):
"""
Private method to handle a syntax error in the debugged program.
Arguments
status -- information about the syntax error
"""
self.resetUI()
self.ui.setActiveWindow()
self.ui.raiseW()
try:
message, (fn, ln, cn) = eval(status)
if fn is None:
fn = ''
except:
QMessageBox.critical(self.ui,Program,
self.trUtf8('The program being debugged contains an unspecified syntax error.'))
return
self.viewmanager.setFileLine(fn,ln,1)
QMessageBox.critical(self.ui,Program,
self.trUtf8('The file <b>%1</b> contains the syntax error <b>%2</b> at line <b>%3</b>.')
.arg(fn)
.arg(message)
.arg(ln))
def handleException(self,status):
"""
Private method to handle an exception of the debugged program.
Arguments
status -- exception information
"""
self.ui.setActiveWindow()
self.ui.raiseW()
qApp.processEvents()
try:
exclist = eval(status)
except:
QMessageBox.critical(self.ui,Program,
self.trUtf8('An unhandled exception occured. See the shell window for details.'))
return
exctype, msg, (fn, ln) = exclist[:3]
if (self.exceptions and \
(not len(self.excList) or \
(len(self.excList) and str(exctype) in self.excList)))\
or exctype.startswith('unhandled'):
self.viewmanager.setFileLine(fn,ln,1)
res = QMessageBox.critical(self.ui,Program,
self.trUtf8('The debugged program raised the exception <b>%1</b><br>"<b>%2</b>"<br>File: <b>%3</b>, Line: <b>%4</b>')
.arg(str(exctype))
.arg(msg)
.arg(fn)
.arg(ln),
self.trUtf8('Continue'), self.trUtf8('Break'))
if res == 1:
stack = []
for fn, ln in exclist[2:]:
stack.append((fn, ln, ''))
self.emit(PYSIGNAL('clientStack'),(stack,))
self.getClientVariables()
return
if self.lastAction != -1:
self.actions[self.lastAction]()
def handleClientGone(self,unplanned):
"""
Private method to handle the disconnection of the debugger client.
Arguments
unplanned -- 1 if the client died, 0 otherwise
"""
if unplanned:
self.resetUI()
QMessageBox.information(self.ui,Program,
self.trUtf8('The program being debugged has terminated unexpectedly.'))
def getClientVariables(self):
"""
Private method to request the global and local variables.
In the first step, the global variables are requested from the client.
Once these have been received, the local variables are requested.
This happens in the method 'handleClientVariables'.
"""
# get globals first
self.dbs.remoteClientVariables(1, self.globalsVarFilter)
# the local variables are requested once we have received the globals
def handleClientVariables(self, vars):
"""
Private method to write the clients variables to the user interface.
Arguments
vars -- the list of variables from the client
"""
vlist = eval(vars)
scope = vlist[0]
try:
vlist = vlist[1:]
except:
vlist = []
if scope == 1:
self.sbv.showVariables(vlist, 1)
# now get the local variables
self.dbs.remoteClientVariables(0, self.localsVarFilter)
elif scope == 0:
self.sbv.showVariables(vlist, 0)
elif scope == -1:
vlist = [('None','','')]
self.sbv.showVariables(vlist, 0)
if scope < 1:
self.debugActGrp.setEnabled(1)
self.debugActGrp2.setEnabled(1)
def handleConfigFilters(self):
"""
Private slot for displaying the variables filter configuration dialog.
"""
result = self.dbgFilterDialog.exec_loop()
if result == QDialog.Accepted:
(self.localsVarFilter, self.globalsVarFilter) = \
self.dbgFilterDialog.getSelection()
else:
self.dbgFilterDialog.setSelection(
self.localsVarFilter, self.globalsVarFilter)
self.sbv.setLocalVariablesFilter(self.localsVarFilter)
def handleExceptionsFilter(self):
"""
Private slot for displaying the exception filter dialog.
"""
dlg = ExceptionsFilterDialog(self.excList)
if dlg.exec_loop() == QDialog.Accepted:
self.excList = dlg.getExceptionsList()
def handleToggleBreakpoint(self):
"""
Private slot to handle the 'Set/Reset breakpoint' action.
"""
editor = self.viewmanager.activeWindow()
line, index = editor.getCursorPosition()
line += 1
state = Qt.LeftButton
editor.handleBreakpoint(line, state)
def handleToggleCBreakpoint(self):
"""
Private slot to handle the 'SetChange conditional breakpoint' action.
"""
editor = self.viewmanager.activeWindow()
line, index = editor.getCursorPosition()
line += 1
state = Qt.LeftButton | Qt.ShiftButton
editor.handleBreakpoint(line, state)
def handleAllFileBp(self):
"""
Private slot for displaying the breakpoints of the current file.
"""
fn = self.viewmanager.getActiveName()
if fn is not None:
BreakpointDialog(self.ui, 'BPDialog', 1, Qt.WDestructiveClose,
fn).exec_loop()
else:
QMessageBox.information(self.ui, Program,
self.trUtf8('No source window active'), QMessageBox.Ok)
def handleAllBp(self):
"""
Private slot for displaying all breakpoints.
"""
BreakpointDialog(self.ui, 'BPDialog', 1, Qt.WDestructiveClose).exec_loop()
def handleProjectBp(self):
"""
Private slot to display all breakpoints of the current project
"""
BreakpointDialog(self.ui, 'BPDialog', 1, Qt.WDestructiveClose,
'project').exec_loop()
def handleCoverageScript(self):
"""
Private slot to handle the coverage of script action.
"""
self.handleCoverage(0)
def handleCoverageProject(self):
"""
Private slot to handle the coverage of project action.
"""
self.handleCoverage(1)
def handleCoverage(self, runProject):
"""
Private method to handle the coverage actions.
Arguments
runProject -- flag indicating coverage of the current project (1)
or script (0)
"""
# Get the command line arguments, the working directory and the
# exception reporting flag.
if runProject:
cap = self.trUtf8("Coverage of Project")
else:
cap = self.trUtf8("Coverage of Script")
dlg = StartDialog(cap, self.argvHistory, self.wdHistory,
self.exceptions, self.ui, 2)
if dlg.exec_loop() == QDialog.Accepted:
argv, wd, exceptions = dlg.getData()
eraseCoverage = dlg.getCoverageData()
if runProject:
project = self.ui.getProject()
fn = project.getMainScript(1)
if fn is None:
QMessageBox.critical(self.ui,
self.trUtf8("Coverage of Project"),
self.trUtf8("There is no main script defined for the"
" current project. Aborting"),
self.trUtf8("&OK"))
return
if not project.saveAllScripts():
return
# save the info for later use
project.setDbgInfo(argv, wd, exceptions, self.excList)
self.lastStartAction = 6
else:
editor = self.viewmanager.activeWindow()
if editor is None:
return
if not self.viewmanager.checkDirty(editor) or \
editor.getFileName() is None:
return
fn = editor.getFileName()
self.lastStartAction = 5
# save the filename for use by the restart method
self.lastDebuggedFile = fn
self.restartAct.setEnabled(1)
# This moves any previous occurence of these arguments to the head
# of the list.
self.argvHistory.remove(argv)
self.argvHistory.prepend(argv)
self.wdHistory.remove(wd)
self.wdHistory.prepend(wd)
# Save the exception flags
self.exceptions = exceptions
# Hide all error highlights
self.viewmanager.unhighlight()
# Ask the client to open the new program.
self.dbs.remoteCoverage(fn,argv,wd,eraseCoverage)
def handleProfileScript(self):
"""
Private slot to handle the profile script action.
"""
self.handleProfile(0)
def handleProfileProject(self):
"""
Private slot to handle the profile project action.
"""
self.handleProfile(1)
def handleProfile(self, runProject):
"""
Private method to handle the profile actions.
Arguments
runProject -- flag indicating profiling of the current project (1)
or script (0)
"""
# Get the command line arguments, the working directory and the
# exception reporting flag.
if runProject:
cap = self.trUtf8("Profile of Project")
else:
cap = self.trUtf8("Profile of Script")
dlg = StartDialog(cap, self.argvHistory, self.wdHistory,
self.exceptions, self.ui, 3)
if dlg.exec_loop() == QDialog.Accepted:
argv, wd, exceptions = dlg.getData()
eraseTimings = dlg.getCoverageData()
if runProject:
project = self.ui.getProject()
fn = project.getMainScript(1)
if fn is None:
QMessageBox.critical(self.ui,
self.trUtf8("Profile of Project"),
self.trUtf8("There is no main script defined for the"
" current project. Aborting"),
self.trUtf8("&OK"))
return
if not project.saveAllScripts():
return
# save the info for later use
project.setDbgInfo(argv, wd, exceptions, self.excList)
self.lastStartAction = 8
else:
editor = self.viewmanager.activeWindow()
if editor is None:
return
if not self.viewmanager.checkDirty(editor) or \
editor.getFileName() is None:
return
fn = editor.getFileName()
self.lastStartAction = 7
# save the filename for use by the restart method
self.lastDebuggedFile = fn
self.restartAct.setEnabled(1)
# This moves any previous occurence of these arguments to the head
# of the list.
self.argvHistory.remove(argv)
self.argvHistory.prepend(argv)
self.wdHistory.remove(wd)
self.wdHistory.prepend(wd)
# Save the exception flags
self.exceptions = exceptions
# Hide all error highlights
self.viewmanager.unhighlight()
# Ask the client to open the new program.
self.dbs.remoteProfile(fn,argv,wd,eraseTimings)
def handleRunScript(self):
"""
Private slot to handle the run script action.
"""
self.handleRun(0)
def handleRunProject(self):
"""
Private slot to handle the run project action.
"""
self.handleRun(1)
def handleRun(self, runProject):
"""
Private method to handle the run actions.
Arguments
runProject -- flag indicating running the current project (1)
or script (0)
"""
# Get the command line arguments, the working directory and the
# exception reporting flag.
if runProject:
cap = self.trUtf8("Run Project")
else:
cap = self.trUtf8("Run Script")
dlg = StartDialog(cap, self.argvHistory, self.wdHistory,
self.exceptions, self.ui, 1)
if dlg.exec_loop() == QDialog.Accepted:
argv, wd, exceptions = dlg.getData()
if runProject:
project = self.ui.getProject()
fn = project.getMainScript(1)
if fn is None:
QMessageBox.critical(self.ui,
self.trUtf8("Run Project"),
self.trUtf8("There is no main script defined for the"
" current project. Aborting"),
self.trUtf8("&OK"))
return
if not project.saveAllScripts():
return
# save the info for later use
project.setDbgInfo(argv, wd, exceptions, self.excList)
self.lastStartAction = 4
else:
editor = self.viewmanager.activeWindow()
if editor is None:
return
if not self.viewmanager.checkDirty(editor) or \
editor.getFileName() is None:
return
fn = editor.getFileName()
self.lastStartAction = 3
# save the filename for use by the restart method
self.lastDebuggedFile = fn
self.restartAct.setEnabled(1)
# This moves any previous occurence of these arguments to the head
# of the list.
self.argvHistory.remove(argv)
self.argvHistory.prepend(argv)
self.wdHistory.remove(wd)
self.wdHistory.prepend(wd)
# Save the exception flags
self.exceptions = exceptions
# Hide all error highlights
self.viewmanager.unhighlight()
# Ask the client to open the new program.
self.dbs.remoteRun(fn,argv,wd)
def handleDebugScript(self):
"""
Private slot to handle the debug script action.
"""
self.handleDebug(0)
def handleDebugProject(self):
"""
Private slot to handle the debug project action.
"""
self.handleDebug(1)
def handleDebug(self, debugProject):
"""
Private method to handle the debug actions.
Arguments
debugProject -- flag indicating debugging the current project (1)
or script (0)
"""
# Get the command line arguments, the working directory and the
# exception reporting flag.
if debugProject:
cap = self.trUtf8("Debug Project")
else:
cap = self.trUtf8("Debug Script")
dlg = StartDialog(cap, self.argvHistory, self.wdHistory,
self.exceptions, self.ui, 0)
if dlg.exec_loop() == QDialog.Accepted:
argv, wd, exceptions = dlg.getData()
if debugProject:
project = self.ui.getProject()
fn = project.getMainScript(1)
if fn is None:
QMessageBox.critical(self.ui,
self.trUtf8("Debug Project"),
self.trUtf8("There is no main script defined for the"
" current project. No debugging possible."),
self.trUtf8("&OK"))
return
if not project.saveAllScripts():
return
# save the info for later use
project.setDbgInfo(argv, wd, exceptions, self.excList)
self.lastStartAction = 2
else:
editor = self.viewmanager.activeWindow()
if editor is None:
return
if not self.viewmanager.checkDirty(editor) or \
editor.getFileName() is None:
return
fn = editor.getFileName()
self.lastStartAction = 1
# save the filename for use by the restart method
self.lastDebuggedFile = fn
self.restartAct.setEnabled(1)
# This moves any previous occurence of these arguments to the head
# of the list.
self.argvHistory.remove(argv)
self.argvHistory.prepend(argv)
self.wdHistory.remove(wd)
self.wdHistory.prepend(wd)
# Save the exception flags
self.exceptions = exceptions
# Hide all error highlights
self.viewmanager.unhighlight()
# Show the local variables viewer, hide the others
self.sbv.showVariablesTab(0) # locals viewer on top
if wd.isEmpty():
self.sbv.setWD(os.path.dirname(os.path.abspath(str(fn))))
else:
self.sbv.setWD(str(wd))
# Ask the client to open the new program.
self.dbs.remoteLoad(fn,argv,wd)
# Signal that we have started a debugging session
self.emit(PYSIGNAL('debuggingStarted'), (fn,))
def handleRestart(self):
"""
Private slot to handle the restart action to restart the last debugged file.
"""
# first save any changes
if self.lastStartAction in [1, 3]:
dummy, editor = self.viewmanager.getEditor(self.lastDebuggedFile)
if not self.viewmanager.checkDirty(editor):
return
elif self.lastStartAction in [2, 4]:
project = self.ui.getProject()
if not project.saveAllScripts():
return
else:
return # should not happen
# get the saved stuff
wd = self.wdHistory[0]
argv = self.argvHistory[0]
fn = self.lastDebuggedFile
# Hide all error highlights
self.viewmanager.unhighlight()
if self.lastStartAction in [1, 2]:
# Show the local variables viewer, hide the others
self.sbv.showVariablesTab(0) # locals viewer on top
if wd.isEmpty():
self.sbv.setWD(os.path.dirname(os.path.abspath(str(fn))))
else:
self.sbv.setWD(str(wd))
# Ask the client to open the new program.
self.dbs.remoteLoad(fn,argv,wd)
# Signal that we have started a debugging session
self.emit(PYSIGNAL('debuggingStarted'), (fn,))
elif self.lastStartAction in [3, 4]:
# Ask the client to open the new program.
self.dbs.remoteRun(fn,argv,wd)
def handlePassiveDebugStarted(self):
"""
Private slot to handle a passive debug session start.
"""
# Hide all error highlights
self.viewmanager.unhighlight()
# Show the local variables viewer, hide the others
self.sbv.showVariablesTab(0) # locals viewer on top
def handleContinue(self):
"""
Private method to handle the Continue action.
"""
self.lastAction=0
self.enterRemote()
self.dbs.remoteContinue()
def handleStep(self):
"""
Private method to handle the Step action.
"""
self.lastAction=1
self.enterRemote()
self.dbs.remoteStep()
def handleStepOver(self):
"""
Private method to handle the Step Over action.
"""
self.lastAction=2
self.enterRemote()
self.dbs.remoteStepOver()
def handleStepOut(self):
"""
Private method to handle the Step Out action.
"""
self.lastAction=3
self.enterRemote()
self.dbs.remoteStepOut()
def handleStepQuit(self):
"""
Private method to handle the Step Quit action.
"""
self.lastAction=4
self.enterRemote()
self.dbs.remoteStepQuit()
self.resetUI()
def handleEval(self):
"""
Private method to handle the Eval action.
"""
# Get the command line arguments.
if len(self.evalHistory) > 0:
curr = 0
else:
curr = -1
arg, ok = QInputDialog.getItem(
self.trUtf8('Evaluate'),
self.trUtf8('Enter the statement to evaluate'),
self.evalHistory,curr,1,self.ui)
if ok:
if arg.isNull():
return
# This moves any previous occurence of this expression to the head
# of the list.
self.evalHistory.remove(arg)
self.evalHistory.prepend(arg)
self.dbs.remoteEval(arg)
def handleExec(self):
"""
Private method to handle the Exec action.
"""
# Get the command line arguments.
if len(self.execHistory) > 0:
curr = 0
else:
curr = -1
stmt, ok = QInputDialog.getItem(
self.trUtf8('Execute'),
self.trUtf8('Enter the statement to execute'),
self.execHistory,curr,1,self.ui)
if ok:
if stmt.isNull():
return
# This moves any previous occurence of this statement to the head
# of the list.
self.execHistory.remove(stmt)
self.execHistory.prepend(stmt)
self.dbs.remoteExec(stmt)
def enterRemote(self):
"""
Private method to update the user interface.
This method is called just prior to executing some of
the program being debugged.
"""
# Disable further debug commands from the user.
self.debugActGrp.setEnabled(0)
self.debugActGrp2.setEnabled(0)
self.viewmanager.unhighlight(1)
def getFileBreakpoints(self, fn):
"""
Public method to get all file breakpoints.
Arguments
fn -- filename (string)
Returns
list of file breakpoints
"""
return self.dbs.getFileBreakpoints(fn)
def getAllBreakpoints(self):
"""
Public method to get all breakpoints
Returns
list of all breakpoints
"""
return self.dbs.getAllBreakpoints()
def getProjectBreakpoints(self):
"""
Public method to get all breakpoints of the current project
Returns
list of breakpoints belonging to the current project
"""
return self.dbs.getProjectBreakpoints(self.ui.getProject().getSources(1))
def getActions(self):
"""
Public method to get a list of all actions.
Returns
list of all actions (list of QAction)
"""
actionList = []
for act in self.queryList("QAction"):
if not isinstance(act, QActionGroup):
actionList.append(act)
return actionList
|