# -*- 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('clientVariable'),self.handleClientVariable)
        self.connect(dbs,PYSIGNAL('clientClearBreak'),self.handleClientClearBreak)
        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)
        self.connect(vm,PYSIGNAL('checkActions'),self.checkActions)
        self.connect(vm,PYSIGNAL('cursorChanged'),self.handleCursorChanged)
        self.connect(vm,PYSIGNAL('breakpointToggled'),self.handleCursorChanged)
        
        # 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('Toggle Breakpoint'),
                QIconSet(IconBreakpointToggle),
                self.trUtf8('Toggle Breakpoint'), Qt.Key_F11,
                self.dbgSetBpActGrp)
        act.setStatusTip(self.trUtf8('Toggle Breakpoint'))
        act.setWhatsThis(self.trUtf8(
            """<b>Toggle Breakpoint</b>"""
            """<p>Toggles a breakpoint at the current line of the"""
            """ current editor.</p>"""
        ))
        self.connect(act,SIGNAL('activated()'), self.handleToggleBreakpoint)
        
        self.dbgEditBpAct = QAction(self.trUtf8('Edit Breakpoint'),
                QIconSet(IconCBreakpointToggle),
                self.trUtf8('Edit Breakpoint...'), Qt.Key_F12,
                self.dbgSetBpActGrp)
        self.dbgEditBpAct.setStatusTip(self.trUtf8('Edit Breakpoint'))
        self.dbgEditBpAct.setWhatsThis(self.trUtf8(
            """<b>Edit Breakpoint</b>"""
            """<p>Opens a dialog to edit the breakpoints properties."""
            """ It works at the current line of the current editor.</p>"""
        ))
        self.connect(self.dbgEditBpAct,SIGNAL('activated()'), self.handleEditBreakpoint)

        self.dbgNextBpAct = QAction(self.trUtf8('Next Breakpoint'),
                QIconSet(IconBreakpointNext),
                self.trUtf8('Next Breakpoint'),
                QKeySequence(self.trUtf8("CTRL+Shift+PgDown","Debug|Next Breakpoint")),
                self.dbgSetBpActGrp)
        self.dbgNextBpAct.setStatusTip(self.trUtf8('Next Breakpoint'))
        self.dbgNextBpAct.setWhatsThis(self.trUtf8(
            """<b>Next Breakpoint</b>"""
            """<p>Go to next breakpoint of the current editor.</p>"""
        ))
        self.connect(self.dbgNextBpAct,SIGNAL('activated()'), self.handleNextBreakpoint)

        self.dbgPrevBpAct = QAction(self.trUtf8('Previous Breakpoint'),
                QIconSet(IconBreakpointPrevious),
                self.trUtf8('Previous Breakpoint'),
                QKeySequence(self.trUtf8("CTRL+Shift+PgUp","Debug|Previous Breakpoint")),
                self.dbgSetBpActGrp)
        self.dbgPrevBpAct.setStatusTip(self.trUtf8('Previous Breakpoint'))
        self.dbgPrevBpAct.setWhatsThis(self.trUtf8(
            """<b>Previous Breakpoint</b>"""
            """<p>Go to previous breakpoint of the current editor.</p>"""
        ))
        self.connect(self.dbgPrevBpAct,SIGNAL('activated()'), self.handlePreviousBreakpoint)

        act = QAction(self.trUtf8('Clear Breakpoints'),
                self.trUtf8('Clear Breakpoints'),
                QKeySequence(self.trUtf8("CTRL+Shift+C","Debug|Clear Breakpoints")),
                self.dbgSetBpActGrp)
        act.setStatusTip(self.trUtf8('Clear Breakpoints'))
        act.setWhatsThis(self.trUtf8(
            """<b>Clear Breakpoints</b>"""
            """<p>Clear breakpoints of all editors.</p>"""
        ))
        self.connect(act,SIGNAL('activated()'), self.handleClearBreakpoints)

        self.dbgAllBpActGrp = QActionGroup(self)
        
        self.dbgFileBpAct = QAction(self.trUtf8('File Breakpoints'),
                self.trUtf8('&File Breakpoints...'), 0, self.dbgAllBpActGrp)
        self.dbgFileBpAct.setStatusTip(self.trUtf8('Show breakpoints of the current file'))
        self.dbgFileBpAct.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(self.dbgFileBpAct,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())
        self.breakpointsMenu = QPopupMenu(menu)
        
        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.insertItem(self.trUtf8('&Breakpoints'), self.breakpointsMenu)
        self.connect(self.breakpointsMenu,SIGNAL('aboutToShow()'),self.handleShowBreakpointsMenu)
        self.connect(self.breakpointsMenu,SIGNAL('activated(int)'),self.handleBreakpointSelected)
        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)
        tb.addSeparator()
        self.dbgSetBpActGrp.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, fn):
        """
        Private slot to handle the editorOpened signal.
        
        Arguments
        
            fn -- filename of the opened editor
        """
        self.dbgAllBpActGrp.setEnabled(1)
        self.editorOpen = 1
        
        if fn:
            editor = self.viewmanager.getOpenEditor(fn)
        else:
            editor = None
        self.checkActions(editor)
        
    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 checkActions(self, editor):
        """
        Private slot to check some actions for their enable/disable status.
        
        Arguments
        
            editor -- editor window
        """
        if editor:
            fn = editor.getFileName()
        else:
            fn = None
            
        if fn and fn.endswith('.py'):
            if not self.passive:
                self.runAct.setEnabled(1)
                self.coverageAct.setEnabled(1)
                self.profileAct.setEnabled(1)
                self.debugAct.setEnabled(1)
            self.dbgSetBpActGrp.setEnabled(1)
            if editor.curLineHasBreakpoint():
                self.dbgEditBpAct.setEnabled(1)
            else:
                self.dbgEditBpAct.setEnabled(0)
            if editor.hasBreakpoints():
                self.dbgNextBpAct.setEnabled(1)
                self.dbgPrevBpAct.setEnabled(1)
                self.dbgFileBpAct.setEnabled(1)
            else:
                self.dbgNextBpAct.setEnabled(0)
                self.dbgPrevBpAct.setEnabled(0)
                self.dbgFileBpAct.setEnabled(0)
        else:
            self.runAct.setEnabled(0)
            self.coverageAct.setEnabled(0)
            self.profileAct.setEnabled(0)
            self.debugAct.setEnabled(0)
            self.dbgSetBpActGrp.setEnabled(0)
            self.dbgFileBpAct.setEnabled(0)
        
    def handleCursorChanged(self, editor):
        """
        Private slot handling the cursorChanged signal of the viewmanager.
        
        Arguments
        
            editor -- editor window
        """
        if editor is None:
            return
            
        fn = editor.getFileName()
            
        if fn and fn.endswith('.py'):
            if editor.curLineHasBreakpoint():
                self.dbgEditBpAct.setEnabled(1)
            else:
                self.dbgEditBpAct.setEnabled(0)
            if editor.hasBreakpoints():
                self.dbgNextBpAct.setEnabled(1)
                self.dbgPrevBpAct.setEnabled(1)
                self.dbgFileBpAct.setEnabled(1)
            else:
                self.dbgNextBpAct.setEnabled(0)
                self.dbgPrevBpAct.setEnabled(0)
                self.dbgFileBpAct.setEnabled(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
            
        try:
            exctype, msg, (fn, ln) = exclist[:3]
            noInfo = 0
        except ValueError:
            exctype, msg = exclist[:2]
            noInfo = 1
        if (self.exceptions and \
            (not len(self.excList) or \
             (len(self.excList) and str(exctype) in self.excList)))\
           or exctype.startswith('unhandled'):
            if noInfo:
                res = QMessageBox.critical(self.ui,Program,
                    self.trUtf8('The debugged program raised the exception <b>%1</b><br>"<b>%2</b>"')
                        .arg(str(exctype))
                        .arg(msg),
                    self.trUtf8('Continue'))
            else:
                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 handleClientVariable(self, vars):
        """
        Private method to write the contents of a clients classvariable to the user interface.
        
        Arguments
        
            vars -- the list of members of a classvariable from the client
        """
        vlist = eval(vars)
        scope = vlist[0]
        try:
            vlist = vlist[1:]
        except:
            vlist = []
            
        if scope == 1:
            self.sbv.showVariable(vlist, 1)
        elif scope == 0:
            self.sbv.showVariable(vlist, 0)
            
    def handleClientClearBreak(self, filename, lineno):
        """
        Private method to clear a temporary breakpoint.
        """
        editor = self.viewmanager.getOpenEditor(filename)
        if editor is not None:
            editor.clearBreakpoint(lineno)
        
    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().handleToggleBreakpoint()
        
    def handleEditBreakpoint(self):
        """
        Private slot to handle the 'Edit breakpoint' action.
        """
        editor = self.viewmanager.activeWindow().handleEditBreakpoint()
        
    def handleNextBreakpoint(self):
        """
        Private slot to handle the 'Next breakpoint' action.
        """
        self.viewmanager.activeWindow().handleNextBreakpoint()
        
    def handlePreviousBreakpoint(self):
        """
        Private slot to handle the 'Previous breakpoint' action.
        """
        self.viewmanager.activeWindow().handlePreviousBreakpoint()
        
    def handleClearBreakpoints(self):
        """
        Private slot to handle the 'Clear breakpoints' action.
        """
        for editor in self.viewmanager.editors:
            editor.handleClearBreakpoints()
        
    def handleShowBreakpointsMenu(self):
        """
        Private method to handle the show breakpoints menu signal.
        """
        self.breakpoints = {}
        self.breakpointsMenu.clear()
        
        filenames = self.viewmanager.getOpenFilenames()
        filenames.sort()
        for filename in filenames:
            editor = self.viewmanager.getOpenEditor(filename)
            for line, cond, _, _, _ in editor.getBreakpoints():
                if len(filename) > 40:
                    dots = "..."
                else:
                    dots = ""
                if cond is None:
                    formattedCond = ""
                else:
                    formattedCond = " : %s" % str(cond)[:20]
                id = self.breakpointsMenu.insertItem(\
                        "%s%s : %d%s" % \
                        (dots, filename[-40:], line, formattedCond))
                self.breakpoints[id] = (filename, line)
    
    def handleBreakpointSelected(self, id):
        """
        Private method to handle the breakpoint selected signal.
        
        Arguments
        
            id -- index of the selected menu entry
                This acts as an index into the list of breakpoints
                that was created, when the breakpoints menu was built.
        """
        self.viewmanager.displayPythonFile(\
            self.breakpoints[id][0], self.breakpoints[id][1])
        
    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, fn):
        """
        Private slot to handle a passive debug session start.
        
        Arguments
        
            fn -- filename of the debugged script
        """
        # Hide all error highlights
        self.viewmanager.unhighlight()
        
        # Show the local variables viewer, hide the others
        self.sbv.showVariablesTab(0) # locals viewer on top
        
        # Set filename of script being debugged
        self.ui.currentProg = fn
        
    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
        """
        editor = self.viewmanager.getOpenEditor(fn)
        if editor is not None:
            return editor.getBreakpoints()
        else:
            return []
        
    def getAllBreakpoints(self):
        """
        Public method to get all breakpoints
        
        Returns
        
            list of all breakpoints
        """
        files = self.viewmanager.getOpenFilenames()
        bpDict = {}
        for file in files:
            bpList = self.viewmanager.getOpenEditor(file).getBreakpoints()
            if bpList:
                bpDict[file] = bpList
                
        return bpDict
        
    def getProjectBreakpoints(self):
        """
        Public method to get all breakpoints of the current project
        
        Returns
        
            list of breakpoints belonging to the current project
        """
        files = self.ui.getProject().getSources(1)
        bpDict = {}
        for file in files:
            editor = self.viewmanager.getOpenEditor(file)
            if editor is not None:
                bpList = editor.getBreakpoints()
                if bpList:
                    bpDict[file] = bpList
                
        return bpDict

    def newBreakpointWithProperties(self, fn, line, properties):
        """
        Public method to set a new breakpoint and its properties.
        
        Arguments
        
            fn -- filename of the breakpoint operation (string)
            
            line -- line number of the breakpoint
            
            properties -- properties for the breakpoint (tuple)
                (condition, temporary flag, enabled flag, ignore count)
        """
        try:
            dummy, editor = self.viewmanager.getEditor(fn)
        except IOError:
            return
        editor.newBreakpointWithProperties(line, properties)
        
    def toggleBreakpoint(self, fn, line):
        """
        Public method to toggle a breakpoint.
        
        Arguments
        
            fn -- filename of the breakpoint operation (string)
            
            line -- line number of the breakpoint
        """
        editor = self.viewmanager.getOpenEditor(fn)
        if editor is not None:
            editor.toggleBreakpoint(line)
        
    def setBreakpointProperties(self, fn, line, properties):
        """
        Public method to set a breakpoints properties.
        
        Arguments
        
            fn -- filename of the breakpoint operation (string)
            
            line -- line number of the breakpoint
            
            properties -- properties for the breakpoint (tuple)
                (condition, temporary flag, enabled flag, ignore count)
        """
        editor = self.viewmanager.getOpenEditor(fn)
        if editor is not None:
            editor.setBreakpointProperties(line, properties)
        
    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
