"Fossies" - the Fresh Open Source Software Archive

Member "eric6-20.9/eric/eric6/Debugger/DebugUI.py" (4 Jul 2020, 93110 Bytes) of package /linux/misc/eric6-20.9.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "DebugUI.py" see the Fossies "Dox" file reference documentation.

    1 # -*- coding: utf-8 -*-
    2 
    3 # Copyright (c) 2002 - 2020 Detlev Offenbach <detlev@die-offenbachs.de>
    4 #
    5 
    6 """
    7 Module implementing the debugger UI.
    8 """
    9 
   10 
   11 import os
   12 
   13 from PyQt5.QtCore import pyqtSignal, QObject, Qt
   14 from PyQt5.QtGui import QKeySequence
   15 from PyQt5.QtWidgets import QMenu, QToolBar, QApplication, QDialog
   16 
   17 from UI.Info import Program
   18 
   19 from .DebugClientCapabilities import (
   20     HasDebugger, HasInterpreter, HasProfiler, HasCoverage
   21 )
   22 import Preferences
   23 import Utilities
   24 import UI.PixmapCache
   25 import UI.Config
   26 
   27 from E5Gui.E5Action import E5Action, createActionGroup
   28 from E5Gui import E5MessageBox
   29 
   30 from eric6config import getConfig
   31 
   32 
   33 class DebugUI(QObject):
   34     """
   35     Class implementing the debugger part of the UI.
   36     
   37     @signal clientStack(stack) emitted at breaking after a reported exception
   38     @signal compileForms() emitted if changed project forms should be compiled
   39     @signal compileResources() emitted if changed project resources should be
   40         compiled
   41     @signal executeMake() emitted if a project specific make run should be
   42         performed
   43     @signal debuggingStarted(filename) emitted when a debugging session was
   44         started
   45     @signal resetUI() emitted to reset the UI
   46     @signal exceptionInterrupt() emitted after the execution was interrupted
   47         by an exception and acknowledged by the user
   48     @signal appendStdout(msg) emitted when the client program has terminated
   49         and the display of the termination dialog is suppressed
   50     """
   51     clientStack = pyqtSignal(list)
   52     resetUI = pyqtSignal()
   53     exceptionInterrupt = pyqtSignal()
   54     compileForms = pyqtSignal()
   55     compileResources = pyqtSignal()
   56     executeMake = pyqtSignal()
   57     debuggingStarted = pyqtSignal(str)
   58     appendStdout = pyqtSignal(str)
   59     
   60     def __init__(self, ui, vm, debugServer, debugViewer, project):
   61         """
   62         Constructor
   63         
   64         @param ui reference to the main UI
   65         @param vm reference to the viewmanager
   66         @param debugServer reference to the debug server
   67         @param debugViewer reference to the debug viewer widget
   68         @param project reference to the project object
   69         """
   70         super(DebugUI, self).__init__(ui)
   71         
   72         self.ui = ui
   73         self.viewmanager = vm
   74         self.debugServer = debugServer
   75         self.debugViewer = debugViewer
   76         self.project = project
   77         
   78         # Clear some variables
   79         self.projectOpen = False
   80         self.editorOpen = False
   81         
   82         # read the saved debug info values
   83         self.lastUsedVenvName = Preferences.Prefs.settings.value(
   84             'DebugInfo/VirtualEnvironment', '')
   85         self.argvHistory = Preferences.toList(
   86             Preferences.Prefs.settings.value('DebugInfo/ArgumentsHistory'))
   87         self.wdHistory = Preferences.toList(
   88             Preferences.Prefs.settings.value(
   89                 'DebugInfo/WorkingDirectoryHistory'))
   90         self.envHistory = Preferences.toList(
   91             Preferences.Prefs.settings.value('DebugInfo/EnvironmentHistory'))
   92         self.excList = Preferences.toList(
   93             Preferences.Prefs.settings.value('DebugInfo/Exceptions'))
   94         self.excIgnoreList = Preferences.toList(
   95             Preferences.Prefs.settings.value('DebugInfo/IgnoredExceptions'))
   96         self.exceptions = Preferences.toBool(
   97             Preferences.Prefs.settings.value(
   98                 'DebugInfo/ReportExceptions', True))
   99         self.autoClearShell = Preferences.toBool(
  100             Preferences.Prefs.settings.value('DebugInfo/AutoClearShell', True))
  101         self.tracePython = Preferences.toBool(
  102             Preferences.Prefs.settings.value('DebugInfo/TracePython', False))
  103         self.autoContinue = Preferences.toBool(
  104             Preferences.Prefs.settings.value('DebugInfo/AutoContinue', True))
  105         self.forkAutomatically = Preferences.toBool(
  106             Preferences.Prefs.settings.value(
  107                 'DebugInfo/ForkAutomatically', False))
  108         self.forkIntoChild = Preferences.toBool(
  109             Preferences.Prefs.settings.value('DebugInfo/ForkIntoChild', False))
  110         
  111         self.lastDebuggedFile = None
  112         self.lastStartAction = 0    # 0=None, 1=Script, 2=Project
  113         self.clientType = ""
  114         self.lastAction = -1
  115         self.debugActions = [
  116             self.__continue, self.__step, self.__stepOver, self.__stepOut,
  117             self.__stepQuit, self.__runToCursor, self.__moveInstructionPointer
  118         ]
  119         self.localsVarFilter, self.globalsVarFilter = (
  120             Preferences.getVarFilters())
  121         self.debugViewer.setVariablesFilter(
  122             self.globalsVarFilter, self.localsVarFilter)
  123         
  124         # Connect the signals emitted by the debug-server
  125         debugServer.clientGone.connect(self.__clientGone)
  126         debugServer.clientLine.connect(self.__clientLine)
  127         debugServer.clientExit.connect(self.__clientExit)
  128         debugServer.clientSyntaxError.connect(self.__clientSyntaxError)
  129         debugServer.clientException.connect(self.__clientException)
  130         debugServer.clientSignal.connect(self.__clientSignal)
  131         debugServer.clientVariables.connect(self.__clientVariables)
  132         debugServer.clientVariable.connect(self.__clientVariable)
  133         debugServer.clientBreakConditionError.connect(
  134             self.__clientBreakConditionError)
  135         debugServer.clientWatchConditionError.connect(
  136             self.__clientWatchConditionError)
  137         debugServer.passiveDebugStarted.connect(self.__passiveDebugStarted)
  138         debugServer.clientThreadSet.connect(self.__clientThreadSet)
  139         
  140         debugServer.clientThreadList.connect(debugViewer.showThreadList)
  141         
  142         # Connect the signals emitted by the viewmanager
  143         vm.editorOpened.connect(self.__editorOpened)
  144         vm.lastEditorClosed.connect(self.__lastEditorClosed)
  145         vm.checkActions.connect(self.__checkActions)
  146         vm.cursorChanged.connect(self.__cursorChanged)
  147         vm.breakpointToggled.connect(self.__cursorChanged)
  148         
  149         # Connect the signals emitted by the project
  150         project.projectOpened.connect(self.__projectOpened)
  151         project.newProject.connect(self.__projectOpened)
  152         project.projectClosed.connect(self.__projectClosed)
  153         
  154         # Set a flag for the passive debug mode
  155         self.passive = Preferences.getDebugger("PassiveDbgEnabled")
  156         
  157     def variablesFilter(self, scope):
  158         """
  159         Public method to get the variables filter for a scope.
  160         
  161         @param scope flag indicating global (True) or local (False) scope
  162         @return filters list (list of integers)
  163         """
  164         if scope:
  165             return self.globalsVarFilter[:]
  166         else:
  167             return self.localsVarFilter[:]
  168         
  169     def initActions(self):
  170         """
  171         Public method defining the user interface actions.
  172         """
  173         self.actions = []
  174         
  175         self.runAct = E5Action(
  176             self.tr('Run Script'),
  177             UI.PixmapCache.getIcon("runScript"),
  178             self.tr('&Run Script...'),
  179             Qt.Key_F2, 0, self, 'dbg_run_script')
  180         self.runAct.setStatusTip(self.tr('Run the current Script'))
  181         self.runAct.setWhatsThis(self.tr(
  182             """<b>Run Script</b>"""
  183             """<p>Set the command line arguments and run the script outside"""
  184             """ the debugger. If the file has unsaved changes it may be"""
  185             """ saved first.</p>"""
  186         ))
  187         self.runAct.triggered.connect(self.__runScript)
  188         self.actions.append(self.runAct)
  189 
  190         self.runProjectAct = E5Action(
  191             self.tr('Run Project'),
  192             UI.PixmapCache.getIcon("runProject"),
  193             self.tr('Run &Project...'), Qt.SHIFT + Qt.Key_F2, 0, self,
  194             'dbg_run_project')
  195         self.runProjectAct.setStatusTip(self.tr('Run the current Project'))
  196         self.runProjectAct.setWhatsThis(self.tr(
  197             """<b>Run Project</b>"""
  198             """<p>Set the command line arguments and run the current project"""
  199             """ outside the debugger."""
  200             """ If files of the current project have unsaved changes they"""
  201             """ may be saved first.</p>"""
  202         ))
  203         self.runProjectAct.triggered.connect(self.__runProject)
  204         self.actions.append(self.runProjectAct)
  205 
  206         self.coverageAct = E5Action(
  207             self.tr('Coverage run of Script'),
  208             UI.PixmapCache.getIcon("coverageScript"),
  209             self.tr('Coverage run of Script...'), 0, 0, self,
  210             'dbg_coverage_script')
  211         self.coverageAct.setStatusTip(
  212             self.tr('Perform a coverage run of the current Script'))
  213         self.coverageAct.setWhatsThis(self.tr(
  214             """<b>Coverage run of Script</b>"""
  215             """<p>Set the command line arguments and run the script under"""
  216             """ the control of a coverage analysis tool. If the file has"""
  217             """ unsaved changes it may be saved first.</p>"""
  218         ))
  219         self.coverageAct.triggered.connect(self.__coverageScript)
  220         self.actions.append(self.coverageAct)
  221 
  222         self.coverageProjectAct = E5Action(
  223             self.tr('Coverage run of Project'),
  224             UI.PixmapCache.getIcon("coverageProject"),
  225             self.tr('Coverage run of Project...'), 0, 0, self,
  226             'dbg_coverage_project')
  227         self.coverageProjectAct.setStatusTip(
  228             self.tr('Perform a coverage run of the current Project'))
  229         self.coverageProjectAct.setWhatsThis(self.tr(
  230             """<b>Coverage run of Project</b>"""
  231             """<p>Set the command line arguments and run the current project"""
  232             """ under the control of a coverage analysis tool."""
  233             """ If files of the current project have unsaved changes"""
  234             """ they may be saved first.</p>"""
  235         ))
  236         self.coverageProjectAct.triggered.connect(self.__coverageProject)
  237         self.actions.append(self.coverageProjectAct)
  238 
  239         self.profileAct = E5Action(
  240             self.tr('Profile Script'),
  241             UI.PixmapCache.getIcon("profileScript"),
  242             self.tr('Profile Script...'), 0, 0, self, 'dbg_profile_script')
  243         self.profileAct.setStatusTip(self.tr('Profile the current Script'))
  244         self.profileAct.setWhatsThis(self.tr(
  245             """<b>Profile Script</b>"""
  246             """<p>Set the command line arguments and profile the script."""
  247             """ If the file has unsaved changes it may be saved first.</p>"""
  248         ))
  249         self.profileAct.triggered.connect(self.__profileScript)
  250         self.actions.append(self.profileAct)
  251 
  252         self.profileProjectAct = E5Action(
  253             self.tr('Profile Project'),
  254             UI.PixmapCache.getIcon("profileProject"),
  255             self.tr('Profile Project...'), 0, 0, self,
  256             'dbg_profile_project')
  257         self.profileProjectAct.setStatusTip(
  258             self.tr('Profile the current Project'))
  259         self.profileProjectAct.setWhatsThis(self.tr(
  260             """<b>Profile Project</b>"""
  261             """<p>Set the command line arguments and profile the current"""
  262             """ project. If files of the current project have unsaved"""
  263             """ changes they may be saved first.</p>"""
  264         ))
  265         self.profileProjectAct.triggered.connect(self.__profileProject)
  266         self.actions.append(self.profileProjectAct)
  267 
  268         self.debugAct = E5Action(
  269             self.tr('Debug Script'),
  270             UI.PixmapCache.getIcon("debugScript"),
  271             self.tr('&Debug Script...'), Qt.Key_F5, 0, self,
  272             'dbg_debug_script')
  273         self.debugAct.setStatusTip(self.tr('Debug the current Script'))
  274         self.debugAct.setWhatsThis(self.tr(
  275             """<b>Debug Script</b>"""
  276             """<p>Set the command line arguments and set the current line"""
  277             """ to be the first executable Python statement of the current"""
  278             """ editor window. If the file has unsaved changes it may be"""
  279             """ saved first.</p>"""
  280         ))
  281         self.debugAct.triggered.connect(self.__debugScript)
  282         self.actions.append(self.debugAct)
  283 
  284         self.debugProjectAct = E5Action(
  285             self.tr('Debug Project'),
  286             UI.PixmapCache.getIcon("debugProject"),
  287             self.tr('Debug &Project...'), Qt.SHIFT + Qt.Key_F5, 0, self,
  288             'dbg_debug_project')
  289         self.debugProjectAct.setStatusTip(self.tr(
  290             'Debug the current Project'))
  291         self.debugProjectAct.setWhatsThis(self.tr(
  292             """<b>Debug Project</b>"""
  293             """<p>Set the command line arguments and set the current line"""
  294             """ to be the first executable Python statement of the main"""
  295             """ script of the current project. If files of the current"""
  296             """ project have unsaved changes they may be saved first.</p>"""
  297         ))
  298         self.debugProjectAct.triggered.connect(self.__debugProject)
  299         self.actions.append(self.debugProjectAct)
  300 
  301         self.restartAct = E5Action(
  302             self.tr('Restart'),
  303             UI.PixmapCache.getIcon("debugRestart"),
  304             self.tr('Restart'), Qt.Key_F4, 0, self, 'dbg_restart_script')
  305         self.restartAct.setStatusTip(self.tr(
  306             'Restart the last debugged script'))
  307         self.restartAct.setWhatsThis(self.tr(
  308             """<b>Restart</b>"""
  309             """<p>Set the command line arguments and set the current line"""
  310             """ to be the first executable Python statement of the script"""
  311             """ that was debugged last. If there are unsaved changes, they"""
  312             """ may be saved first.</p>"""
  313         ))
  314         self.restartAct.triggered.connect(self.__doRestart)
  315         self.actions.append(self.restartAct)
  316 
  317         self.stopAct = E5Action(
  318             self.tr('Stop'),
  319             UI.PixmapCache.getIcon("stopScript"),
  320             self.tr('Stop'), Qt.SHIFT + Qt.Key_F10, 0,
  321             self, 'dbg_stop_script')
  322         self.stopAct.setStatusTip(self.tr("""Stop the running script."""))
  323         self.stopAct.setWhatsThis(self.tr(
  324             """<b>Stop</b>"""
  325             """<p>This stops the script running in the debugger backend.</p>"""
  326         ))
  327         self.stopAct.triggered.connect(self.__stopScript)
  328         self.actions.append(self.stopAct)
  329 
  330         self.debugActGrp = createActionGroup(self)
  331 
  332         act = E5Action(
  333             self.tr('Continue'),
  334             UI.PixmapCache.getIcon("continue"),
  335             self.tr('&Continue'), Qt.Key_F6, 0,
  336             self.debugActGrp, 'dbg_continue')
  337         act.setStatusTip(
  338             self.tr('Continue running the program from the current line'))
  339         act.setWhatsThis(self.tr(
  340             """<b>Continue</b>"""
  341             """<p>Continue running the program from the current line. The"""
  342             """ program will stop when it terminates or when a breakpoint"""
  343             """ is reached.</p>"""
  344         ))
  345         act.triggered.connect(self.__continue)
  346         self.actions.append(act)
  347 
  348         act = E5Action(
  349             self.tr('Continue to Cursor'),
  350             UI.PixmapCache.getIcon("continueToCursor"),
  351             self.tr('Continue &To Cursor'), Qt.SHIFT + Qt.Key_F6, 0,
  352             self.debugActGrp, 'dbg_continue_to_cursor')
  353         act.setStatusTip(self.tr(
  354             """Continue running the program from the"""
  355             """ current line to the current cursor position"""))
  356         act.setWhatsThis(self.tr(
  357             """<b>Continue To Cursor</b>"""
  358             """<p>Continue running the program from the current line to the"""
  359             """ current cursor position.</p>"""
  360         ))
  361         act.triggered.connect(self.__runToCursor)
  362         self.actions.append(act)
  363         
  364         act = E5Action(
  365             self.tr('Move Instruction Pointer to Cursor'),
  366             UI.PixmapCache.getIcon("moveInstructionPointer"),
  367             self.tr('&Jump To Cursor'), Qt.Key_F12, 0,
  368             self.debugActGrp, 'dbg_jump_to_cursor')
  369         act.setStatusTip(self.tr(
  370             """Skip the code from the"""
  371             """ current line to the current cursor position"""))
  372         act.setWhatsThis(self.tr(
  373             """<b>Move Instruction Pointer to Cursor</b>"""
  374             """<p>Move the Python internal instruction pointer to the"""
  375             """ current cursor position without executing the code in"""
  376             """ between.</p>"""
  377             """<p>It's not possible to jump out of a function or jump"""
  378             """ in a code block, e.g. a loop. In these cases, a error"""
  379             """ message is printed to the log window.</p>"""
  380         ))
  381         act.triggered.connect(self.__moveInstructionPointer)
  382         self.actions.append(act)
  383 
  384         act = E5Action(
  385             self.tr('Single Step'),
  386             UI.PixmapCache.getIcon("step"),
  387             self.tr('Sin&gle Step'), Qt.Key_F7, 0,
  388             self.debugActGrp, 'dbg_single_step')
  389         act.setStatusTip(self.tr('Execute a single Python statement'))
  390         act.setWhatsThis(self.tr(
  391             """<b>Single Step</b>"""
  392             """<p>Execute a single Python statement. If the statement"""
  393             """ is an <tt>import</tt> statement, a class constructor, or a"""
  394             """ method or function call then control is returned to the"""
  395             """ debugger at the next statement.</p>"""
  396         ))
  397         act.triggered.connect(self.__step)
  398         self.actions.append(act)
  399 
  400         act = E5Action(
  401             self.tr('Step Over'),
  402             UI.PixmapCache.getIcon("stepOver"),
  403             self.tr('Step &Over'), Qt.Key_F8, 0,
  404             self.debugActGrp, 'dbg_step_over')
  405         act.setStatusTip(self.tr(
  406             """Execute a single Python statement staying"""
  407             """ in the current frame"""))
  408         act.setWhatsThis(self.tr(
  409             """<b>Step Over</b>"""
  410             """<p>Execute a single Python statement staying in the same"""
  411             """ frame. If the statement is an <tt>import</tt> statement,"""
  412             """ a class constructor, or a method or function call then"""
  413             """ control is returned to the debugger after the statement"""
  414             """ has completed.</p>"""
  415         ))
  416         act.triggered.connect(self.__stepOver)
  417         self.actions.append(act)
  418 
  419         act = E5Action(
  420             self.tr('Step Out'),
  421             UI.PixmapCache.getIcon("stepOut"),
  422             self.tr('Step Ou&t'), Qt.Key_F9, 0,
  423             self.debugActGrp, 'dbg_step_out')
  424         act.setStatusTip(self.tr(
  425             """Execute Python statements until leaving"""
  426             """ the current frame"""))
  427         act.setWhatsThis(self.tr(
  428             """<b>Step Out</b>"""
  429             """<p>Execute Python statements until leaving the current"""
  430             """ frame. If the statements are inside an <tt>import</tt>"""
  431             """ statement, a class constructor, or a method or function"""
  432             """ call then control is returned to the debugger after the"""
  433             """ current frame has been left.</p>"""
  434         ))
  435         act.triggered.connect(self.__stepOut)
  436         self.actions.append(act)
  437 
  438         act = E5Action(
  439             self.tr('Stop'),
  440             UI.PixmapCache.getIcon("stepQuit"),
  441             self.tr('&Stop'), Qt.Key_F10, 0,
  442             self.debugActGrp, 'dbg_stop')
  443         act.setStatusTip(self.tr('Stop debugging'))
  444         act.setWhatsThis(self.tr(
  445             """<b>Stop</b>"""
  446             """<p>Stop the running debugging session.</p>"""
  447         ))
  448         act.triggered.connect(self.__stepQuit)
  449         self.actions.append(act)
  450         
  451         self.dbgFilterAct = E5Action(
  452             self.tr('Variables Type Filter'),
  453             self.tr('Varia&bles Type Filter...'), 0, 0, self,
  454             'dbg_variables_filter')
  455         self.dbgFilterAct.setStatusTip(self.tr(
  456             'Configure variables type filter'))
  457         self.dbgFilterAct.setWhatsThis(self.tr(
  458             """<b>Variables Type Filter</b>"""
  459             """<p>Configure the variables type filter. Only variable types"""
  460             """ that are not selected are displayed in the global or local"""
  461             """ variables window during a debugging session.</p>"""
  462         ))
  463         self.dbgFilterAct.triggered.connect(
  464             self.__configureVariablesFilters)
  465         self.actions.append(self.dbgFilterAct)
  466 
  467         self.excFilterAct = E5Action(
  468             self.tr('Exceptions Filter'),
  469             self.tr('&Exceptions Filter...'), 0, 0, self,
  470             'dbg_exceptions_filter')
  471         self.excFilterAct.setStatusTip(self.tr(
  472             'Configure exceptions filter'))
  473         self.excFilterAct.setWhatsThis(self.tr(
  474             """<b>Exceptions Filter</b>"""
  475             """<p>Configure the exceptions filter. Only exception types"""
  476             """ that are listed are highlighted during a debugging"""
  477             """ session.</p><p>Please note, that all unhandled exceptions"""
  478             """ are highlighted indepent from the filter list.</p>"""
  479         ))
  480         self.excFilterAct.triggered.connect(
  481             self.__configureExceptionsFilter)
  482         self.actions.append(self.excFilterAct)
  483         
  484         self.excIgnoreFilterAct = E5Action(
  485             self.tr('Ignored Exceptions'),
  486             self.tr('&Ignored Exceptions...'), 0, 0,
  487             self, 'dbg_ignored_exceptions')
  488         self.excIgnoreFilterAct.setStatusTip(self.tr(
  489             'Configure ignored exceptions'))
  490         self.excIgnoreFilterAct.setWhatsThis(self.tr(
  491             """<b>Ignored Exceptions</b>"""
  492             """<p>Configure the ignored exceptions. Only exception types"""
  493             """ that are not listed are highlighted during a debugging"""
  494             """ session.</p><p>Please note, that unhandled exceptions"""
  495             """ cannot be ignored.</p>"""
  496         ))
  497         self.excIgnoreFilterAct.triggered.connect(
  498             self.__configureIgnoredExceptions)
  499         self.actions.append(self.excIgnoreFilterAct)
  500 
  501         self.dbgSetBpActGrp = createActionGroup(self)
  502 
  503         self.dbgToggleBpAct = E5Action(
  504             self.tr('Toggle Breakpoint'),
  505             UI.PixmapCache.getIcon("breakpointToggle"),
  506             self.tr('Toggle Breakpoint'),
  507             QKeySequence(self.tr("Shift+F11", "Debug|Toggle Breakpoint")),
  508             0, self.dbgSetBpActGrp, 'dbg_toggle_breakpoint')
  509         self.dbgToggleBpAct.setStatusTip(self.tr('Toggle Breakpoint'))
  510         self.dbgToggleBpAct.setWhatsThis(self.tr(
  511             """<b>Toggle Breakpoint</b>"""
  512             """<p>Toggles a breakpoint at the current line of the"""
  513             """ current editor.</p>"""
  514         ))
  515         self.dbgToggleBpAct.triggered.connect(self.__toggleBreakpoint)
  516         self.actions.append(self.dbgToggleBpAct)
  517         
  518         self.dbgEditBpAct = E5Action(
  519             self.tr('Edit Breakpoint'),
  520             UI.PixmapCache.getIcon("cBreakpointToggle"),
  521             self.tr('Edit Breakpoint...'),
  522             QKeySequence(self.tr("Shift+F12", "Debug|Edit Breakpoint")), 0,
  523             self.dbgSetBpActGrp, 'dbg_edit_breakpoint')
  524         self.dbgEditBpAct.setStatusTip(self.tr('Edit Breakpoint'))
  525         self.dbgEditBpAct.setWhatsThis(self.tr(
  526             """<b>Edit Breakpoint</b>"""
  527             """<p>Opens a dialog to edit the breakpoints properties."""
  528             """ It works at the current line of the current editor.</p>"""
  529         ))
  530         self.dbgEditBpAct.triggered.connect(self.__editBreakpoint)
  531         self.actions.append(self.dbgEditBpAct)
  532 
  533         self.dbgNextBpAct = E5Action(
  534             self.tr('Next Breakpoint'),
  535             UI.PixmapCache.getIcon("breakpointNext"),
  536             self.tr('Next Breakpoint'),
  537             QKeySequence(
  538                 self.tr("Ctrl+Shift+PgDown", "Debug|Next Breakpoint")), 0,
  539             self.dbgSetBpActGrp, 'dbg_next_breakpoint')
  540         self.dbgNextBpAct.setStatusTip(self.tr('Next Breakpoint'))
  541         self.dbgNextBpAct.setWhatsThis(self.tr(
  542             """<b>Next Breakpoint</b>"""
  543             """<p>Go to next breakpoint of the current editor.</p>"""
  544         ))
  545         self.dbgNextBpAct.triggered.connect(self.__nextBreakpoint)
  546         self.actions.append(self.dbgNextBpAct)
  547 
  548         self.dbgPrevBpAct = E5Action(
  549             self.tr('Previous Breakpoint'),
  550             UI.PixmapCache.getIcon("breakpointPrevious"),
  551             self.tr('Previous Breakpoint'),
  552             QKeySequence(
  553                 self.tr("Ctrl+Shift+PgUp", "Debug|Previous Breakpoint")),
  554             0, self.dbgSetBpActGrp, 'dbg_previous_breakpoint')
  555         self.dbgPrevBpAct.setStatusTip(self.tr('Previous Breakpoint'))
  556         self.dbgPrevBpAct.setWhatsThis(self.tr(
  557             """<b>Previous Breakpoint</b>"""
  558             """<p>Go to previous breakpoint of the current editor.</p>"""
  559         ))
  560         self.dbgPrevBpAct.triggered.connect(self.__previousBreakpoint)
  561         self.actions.append(self.dbgPrevBpAct)
  562 
  563         act = E5Action(
  564             self.tr('Clear Breakpoints'),
  565             self.tr('Clear Breakpoints'),
  566             0, 0,
  567             self.dbgSetBpActGrp, 'dbg_clear_breakpoint')
  568         act.setStatusTip(self.tr('Clear Breakpoints'))
  569         act.setWhatsThis(self.tr(
  570             """<b>Clear Breakpoints</b>"""
  571             """<p>Clear breakpoints of all editors.</p>"""
  572         ))
  573         act.triggered.connect(self.__clearBreakpoints)
  574         self.actions.append(act)
  575 
  576         self.debugActGrp.setEnabled(False)
  577         self.dbgSetBpActGrp.setEnabled(False)
  578         self.runAct.setEnabled(False)
  579         self.runProjectAct.setEnabled(False)
  580         self.profileAct.setEnabled(False)
  581         self.profileProjectAct.setEnabled(False)
  582         self.coverageAct.setEnabled(False)
  583         self.coverageProjectAct.setEnabled(False)
  584         self.debugAct.setEnabled(False)
  585         self.debugProjectAct.setEnabled(False)
  586         self.restartAct.setEnabled(False)
  587         self.stopAct.setEnabled(False)
  588         
  589     def initMenus(self):
  590         """
  591         Public slot to initialize the project menu.
  592         
  593         @return the generated menu
  594         """
  595         dmenu = QMenu(self.tr('&Debug'), self.parent())
  596         dmenu.setTearOffEnabled(True)
  597         smenu = QMenu(self.tr('Sta&rt'), self.parent())
  598         smenu.setTearOffEnabled(True)
  599         self.breakpointsMenu = QMenu(self.tr('&Breakpoints'), dmenu)
  600         
  601         smenu.addAction(self.restartAct)
  602         smenu.addAction(self.stopAct)
  603         smenu.addSeparator()
  604         smenu.addAction(self.runAct)
  605         smenu.addAction(self.runProjectAct)
  606         smenu.addSeparator()
  607         smenu.addAction(self.debugAct)
  608         smenu.addAction(self.debugProjectAct)
  609         smenu.addSeparator()
  610         smenu.addAction(self.profileAct)
  611         smenu.addAction(self.profileProjectAct)
  612         smenu.addSeparator()
  613         smenu.addAction(self.coverageAct)
  614         smenu.addAction(self.coverageProjectAct)
  615         
  616         dmenu.addActions(self.debugActGrp.actions())
  617         dmenu.addSeparator()
  618         dmenu.addActions(self.dbgSetBpActGrp.actions())
  619         self.menuBreakpointsAct = dmenu.addMenu(self.breakpointsMenu)
  620         dmenu.addSeparator()
  621         dmenu.addAction(self.dbgFilterAct)
  622         dmenu.addAction(self.excFilterAct)
  623         dmenu.addAction(self.excIgnoreFilterAct)
  624         
  625         self.breakpointsMenu.aboutToShow.connect(self.__showBreakpointsMenu)
  626         self.breakpointsMenu.triggered.connect(self.__breakpointSelected)
  627         dmenu.aboutToShow.connect(self.__showDebugMenu)
  628         
  629         return smenu, dmenu
  630         
  631     def initToolbars(self, toolbarManager):
  632         """
  633         Public slot to initialize the debug toolbars.
  634         
  635         @param toolbarManager reference to a toolbar manager object
  636             (E5ToolBarManager)
  637         @return the generated toolbars (list of QToolBar)
  638         """
  639         starttb = QToolBar(self.tr("Start"), self.ui)
  640         starttb.setIconSize(UI.Config.ToolBarIconSize)
  641         starttb.setObjectName("StartToolbar")
  642         starttb.setToolTip(self.tr('Start'))
  643         
  644         starttb.addAction(self.restartAct)
  645         starttb.addAction(self.stopAct)
  646         starttb.addSeparator()
  647         starttb.addAction(self.runAct)
  648         starttb.addAction(self.runProjectAct)
  649         starttb.addSeparator()
  650         starttb.addAction(self.debugAct)
  651         starttb.addAction(self.debugProjectAct)
  652         
  653         debugtb = QToolBar(self.tr("Debug"), self.ui)
  654         debugtb.setIconSize(UI.Config.ToolBarIconSize)
  655         debugtb.setObjectName("DebugToolbar")
  656         debugtb.setToolTip(self.tr('Debug'))
  657         
  658         debugtb.addActions(self.debugActGrp.actions())
  659         debugtb.addSeparator()
  660         debugtb.addAction(self.dbgToggleBpAct)
  661         debugtb.addAction(self.dbgEditBpAct)
  662         debugtb.addAction(self.dbgNextBpAct)
  663         debugtb.addAction(self.dbgPrevBpAct)
  664         
  665         toolbarManager.addToolBar(starttb, starttb.windowTitle())
  666         toolbarManager.addToolBar(debugtb, debugtb.windowTitle())
  667         toolbarManager.addAction(self.profileAct, starttb.windowTitle())
  668         toolbarManager.addAction(self.profileProjectAct, starttb.windowTitle())
  669         toolbarManager.addAction(self.coverageAct, starttb.windowTitle())
  670         toolbarManager.addAction(self.coverageProjectAct,
  671                                  starttb.windowTitle())
  672         
  673         return [starttb, debugtb]
  674 
  675     def setArgvHistory(self, argsStr, clearHistories=False, history=None):
  676         """
  677         Public slot to initialize the argv history.
  678         
  679         @param argsStr the commandline arguments (string)
  680         @param clearHistories flag indicating, that the list should
  681             be cleared (boolean)
  682         @param history list of history entries to be set (list of strings)
  683         """
  684         if clearHistories:
  685             del self.argvHistory[1:]
  686         elif history is not None:
  687             self.argvHistory = history[:]
  688         else:
  689             if argsStr in self.argvHistory:
  690                 self.argvHistory.remove(argsStr)
  691             self.argvHistory.insert(0, argsStr)
  692 
  693     def setWdHistory(self, wdStr, clearHistories=False, history=None):
  694         """
  695         Public slot to initialize the wd history.
  696         
  697         @param wdStr the working directory (string)
  698         @param clearHistories flag indicating, that the list should
  699             be cleared (boolean)
  700         @param history list of history entries to be set (list of strings)
  701         """
  702         if clearHistories:
  703             del self.wdHistory[1:]
  704         elif history is not None:
  705             self.wdHistory = history[:]
  706         else:
  707             if wdStr in self.wdHistory:
  708                 self.wdHistory.remove(wdStr)
  709             self.wdHistory.insert(0, wdStr)
  710         
  711     def setEnvHistory(self, envStr, clearHistories=False, history=None):
  712         """
  713         Public slot to initialize the env history.
  714         
  715         @param envStr the environment settings (string)
  716         @param clearHistories flag indicating, that the list should
  717             be cleared (boolean)
  718         @param history list of history entries to be set (list of strings)
  719         """
  720         if clearHistories:
  721             del self.envHistory[1:]
  722         elif history is not None:
  723             self.envHistory = history[:]
  724         else:
  725             if envStr in self.envHistory:
  726                 self.envHistory.remove(envStr)
  727             self.envHistory.insert(0, envStr)
  728         
  729     def setExceptionReporting(self, exceptions):
  730         """
  731         Public slot to initialize the exception reporting flag.
  732         
  733         @param exceptions flag indicating exception reporting status (boolean)
  734         """
  735         self.exceptions = exceptions
  736 
  737     def setExcList(self, excList):
  738         """
  739         Public slot to initialize the exceptions type list.
  740         
  741         @param excList list of exception types (list of strings)
  742         """
  743         self.excList = excList[:]   # keep a copy
  744         
  745     def setExcIgnoreList(self, excIgnoreList):
  746         """
  747         Public slot to initialize the ignored exceptions type list.
  748         
  749         @param excIgnoreList list of ignored exception types (list of strings)
  750         """
  751         self.excIgnoreList = excIgnoreList[:]   # keep a copy
  752         
  753     def setAutoClearShell(self, autoClearShell):
  754         """
  755         Public slot to initialize the autoClearShell flag.
  756         
  757         @param autoClearShell flag indicating, that the interpreter window
  758             should be cleared (boolean)
  759         """
  760         self.autoClearShell = autoClearShell
  761 
  762     def setTracePython(self, tracePython):
  763         """
  764         Public slot to initialize the trace Python flag.
  765         
  766         @param tracePython flag indicating if the Python library should be
  767             traced as well (boolean)
  768         """
  769         self.tracePython = tracePython
  770 
  771     def setAutoContinue(self, autoContinue):
  772         """
  773         Public slot to initialize the autoContinue flag.
  774         
  775         @param autoContinue flag indicating, that the debugger should not
  776             stop at the first executable line (boolean)
  777         """
  778         self.autoContinue = autoContinue
  779 
  780     def __editorOpened(self, fn):
  781         """
  782         Private slot to handle the editorOpened signal.
  783         
  784         @param fn filename of the opened editor
  785         """
  786         self.editorOpen = True
  787         
  788         if fn:
  789             editor = self.viewmanager.getOpenEditor(fn)
  790         else:
  791             editor = None
  792         self.__checkActions(editor)
  793         
  794     def __lastEditorClosed(self):
  795         """
  796         Private slot to handle the closeProgram signal.
  797         """
  798         self.editorOpen = False
  799         self.debugAct.setEnabled(False)
  800         self.runAct.setEnabled(False)
  801         self.profileAct.setEnabled(False)
  802         self.coverageAct.setEnabled(False)
  803         self.debugActGrp.setEnabled(False)
  804         self.dbgSetBpActGrp.setEnabled(False)
  805         self.lastAction = -1
  806         if not self.projectOpen:
  807             self.restartAct.setEnabled(False)
  808             self.lastDebuggedFile = None
  809             self.lastStartAction = 0
  810             self.clientType = ""
  811         
  812     def __checkActions(self, editor):
  813         """
  814         Private slot to check some actions for their enable/disable status.
  815         
  816         @param editor editor window
  817         """
  818         if editor:
  819             fn = editor.getFileName()
  820         else:
  821             fn = None
  822         
  823         cap = 0
  824         if fn:
  825             for language in self.debugServer.getSupportedLanguages():
  826                 exts = self.debugServer.getExtensions(language)
  827                 if fn.endswith(exts):
  828                     cap = self.debugServer.getClientCapabilities(language)
  829                     break
  830             else:
  831                 if editor.isPy3File():
  832                     cap = self.debugServer.getClientCapabilities('Python3')
  833                 elif editor.isRubyFile():
  834                     cap = self.debugServer.getClientCapabilities('Ruby')
  835         
  836             if not self.passive:
  837                 self.runAct.setEnabled(cap & HasInterpreter)
  838                 self.coverageAct.setEnabled(cap & HasCoverage)
  839                 self.profileAct.setEnabled(cap & HasProfiler)
  840                 self.debugAct.setEnabled(cap & HasDebugger)
  841             self.dbgSetBpActGrp.setEnabled(cap & HasDebugger)
  842             if editor.curLineHasBreakpoint():
  843                 self.dbgEditBpAct.setEnabled(True)
  844             else:
  845                 self.dbgEditBpAct.setEnabled(False)
  846             if editor.hasBreakpoints():
  847                 self.dbgNextBpAct.setEnabled(True)
  848                 self.dbgPrevBpAct.setEnabled(True)
  849             else:
  850                 self.dbgNextBpAct.setEnabled(False)
  851                 self.dbgPrevBpAct.setEnabled(False)
  852         else:
  853             self.runAct.setEnabled(False)
  854             self.coverageAct.setEnabled(False)
  855             self.profileAct.setEnabled(False)
  856             self.debugAct.setEnabled(False)
  857             self.dbgSetBpActGrp.setEnabled(False)
  858         
  859     def __cursorChanged(self, editor):
  860         """
  861         Private slot handling the cursorChanged signal of the viewmanager.
  862         
  863         @param editor editor window
  864         """
  865         if editor is None:
  866             return
  867         
  868         if editor.isPyFile() or editor.isRubyFile():
  869             if editor.curLineHasBreakpoint():
  870                 self.dbgEditBpAct.setEnabled(True)
  871             else:
  872                 self.dbgEditBpAct.setEnabled(False)
  873             if editor.hasBreakpoints():
  874                 self.dbgNextBpAct.setEnabled(True)
  875                 self.dbgPrevBpAct.setEnabled(True)
  876             else:
  877                 self.dbgNextBpAct.setEnabled(False)
  878                 self.dbgPrevBpAct.setEnabled(False)
  879         
  880     def __projectOpened(self):
  881         """
  882         Private slot to handle the projectOpened signal.
  883         """
  884         self.projectOpen = True
  885         cap = self.debugServer.getClientCapabilities(
  886             self.project.getProjectLanguage())
  887         if not self.passive:
  888             self.debugProjectAct.setEnabled(cap & HasDebugger)
  889             self.runProjectAct.setEnabled(cap & HasInterpreter)
  890             self.profileProjectAct.setEnabled(cap & HasProfiler)
  891             self.coverageProjectAct.setEnabled(cap & HasCoverage)
  892         
  893     def __projectClosed(self):
  894         """
  895         Private slot to handle the projectClosed signal.
  896         """
  897         self.projectOpen = False
  898         self.runProjectAct.setEnabled(False)
  899         self.profileProjectAct.setEnabled(False)
  900         self.coverageProjectAct.setEnabled(False)
  901         self.debugProjectAct.setEnabled(False)
  902         
  903         if not self.editorOpen:
  904             self.restartAct.setEnabled(False)
  905             self.lastDebuggedFile = None
  906             self.lastStartAction = 0
  907             self.clientType = ""
  908         
  909     def clearHistories(self):
  910         """
  911         Public method to clear the various debug histories.
  912         """
  913         self.argvHistory = []
  914         self.wdHistory = []
  915         self.envHistory = []
  916         
  917         Preferences.Prefs.settings.setValue(
  918             'DebugInfo/ArgumentsHistory', self.argvHistory)
  919         Preferences.Prefs.settings.setValue(
  920             'DebugInfo/WorkingDirectoryHistory', self.wdHistory)
  921         Preferences.Prefs.settings.setValue(
  922             'DebugInfo/EnvironmentHistory', self.envHistory)
  923         
  924     def shutdown(self):
  925         """
  926         Public method to perform shutdown actions.
  927         """
  928         # Just save the 10 most recent entries
  929         del self.argvHistory[10:]
  930         del self.wdHistory[10:]
  931         del self.envHistory[10:]
  932         
  933         Preferences.Prefs.settings.setValue(
  934             'DebugInfo/VirtualEnvironment', self.lastUsedVenvName)
  935         Preferences.Prefs.settings.setValue(
  936             'DebugInfo/ArgumentsHistory', self.argvHistory)
  937         Preferences.Prefs.settings.setValue(
  938             'DebugInfo/WorkingDirectoryHistory', self.wdHistory)
  939         Preferences.Prefs.settings.setValue(
  940             'DebugInfo/EnvironmentHistory', self.envHistory)
  941         Preferences.Prefs.settings.setValue(
  942             'DebugInfo/Exceptions', self.excList)
  943         Preferences.Prefs.settings.setValue(
  944             'DebugInfo/IgnoredExceptions', self.excIgnoreList)
  945         Preferences.Prefs.settings.setValue(
  946             'DebugInfo/ReportExceptions', self.exceptions)
  947         Preferences.Prefs.settings.setValue(
  948             'DebugInfo/AutoClearShell', self.autoClearShell)
  949         Preferences.Prefs.settings.setValue(
  950             'DebugInfo/TracePython', self.tracePython)
  951         Preferences.Prefs.settings.setValue(
  952             'DebugInfo/AutoContinue', self.autoContinue)
  953         Preferences.Prefs.settings.setValue(
  954             'DebugInfo/ForkAutomatically', self.forkAutomatically)
  955         Preferences.Prefs.settings.setValue(
  956             'DebugInfo/ForkIntoChild', self.forkIntoChild)
  957         
  958     def shutdownServer(self):
  959         """
  960         Public method to shut down the debug server.
  961         
  962         This is needed to cleanly close the sockets on Win OS.
  963         
  964         @return always true
  965         """
  966         self.debugServer.shutdownServer()
  967         return True
  968         
  969     def __resetUI(self):
  970         """
  971         Private slot to reset the user interface.
  972         """
  973         self.lastAction = -1
  974         self.debugActGrp.setEnabled(False)
  975         if not self.passive:
  976             if self.editorOpen:
  977                 editor = self.viewmanager.activeWindow()
  978             else:
  979                 editor = None
  980             self.__checkActions(editor)
  981             
  982             self.debugProjectAct.setEnabled(self.projectOpen)
  983             self.runProjectAct.setEnabled(self.projectOpen)
  984             self.profileProjectAct.setEnabled(self.projectOpen)
  985             self.coverageProjectAct.setEnabled(self.projectOpen)
  986             if (
  987                 self.lastDebuggedFile is not None and
  988                 (self.editorOpen or self.projectOpen)
  989             ):
  990                 self.restartAct.setEnabled(True)
  991             else:
  992                 self.restartAct.setEnabled(False)
  993             self.stopAct.setEnabled(False)
  994         self.resetUI.emit()
  995         
  996     def __clientLine(self, fn, line, forStack):
  997         """
  998         Private method to handle a change to the current line.
  999         
 1000         @param fn filename (string)
 1001         @param line linenumber (int)
 1002         @param forStack flag indicating this is for a stack dump (boolean)
 1003         """
 1004         self.ui.raise_()
 1005         self.ui.activateWindow()
 1006         if self.ui.getViewProfile() != "debug":
 1007             self.ui.setDebugProfile()
 1008         self.viewmanager.setFileLine(fn, line)
 1009         if not forStack:
 1010             self.__getThreadList()
 1011             self.__getClientVariables()
 1012 
 1013         self.debugActGrp.setEnabled(True)
 1014         
 1015     def __clientExit(self, status, message, quiet):
 1016         """
 1017         Private method to handle the debugged program terminating.
 1018         
 1019         @param status exit code of the debugged program
 1020         @type int
 1021         @param message exit message of the debugged program
 1022         @type str
 1023         @param quiet flag indicating to suppress exit info display
 1024         @type bool
 1025         """
 1026         self.viewmanager.exit()
 1027 
 1028         self.__resetUI()
 1029         
 1030         if not quiet:
 1031             if (
 1032                 not Preferences.getDebugger("SuppressClientExit") or
 1033                 status != 0
 1034             ):
 1035                 if message:
 1036                     info = self.tr("<p>Message: {0}</p>").format(
 1037                         Utilities.html_uencode(message))
 1038                 else:
 1039                     info = ""
 1040                 if self.ui.currentProg is None:
 1041                     E5MessageBox.information(
 1042                         self.ui, Program,
 1043                         self.tr('<p>The program has terminated with an exit'
 1044                                 ' status of {0}.</p>{1}').format(status, info))
 1045                 else:
 1046                     E5MessageBox.information(
 1047                         self.ui, Program,
 1048                         self.tr('<p><b>{0}</b> has terminated with an exit'
 1049                                 ' status of {1}.</p>{2}')
 1050                             .format(Utilities.normabspath(self.ui.currentProg),
 1051                                     status, info))
 1052             else:
 1053                 if message:
 1054                     info = self.tr("Message: {0}").format(
 1055                         Utilities.html_uencode(message))
 1056                 else:
 1057                     info = ""
 1058                 if self.ui.notificationsEnabled():
 1059                     if self.ui.currentProg is None:
 1060                         msg = self.tr(
 1061                             'The program has terminated with an exit status of'
 1062                             ' {0}.\n{1}').format(status, info)
 1063                     else:
 1064                         msg = self.tr(
 1065                             '"{0}" has terminated with an exit status of'
 1066                             ' {1}.\n{2}').format(
 1067                             os.path.basename(self.ui.currentProg), status,
 1068                             info)
 1069                     self.ui.showNotification(
 1070                         UI.PixmapCache.getPixmap("debug48"),
 1071                         self.tr("Program terminated"), msg)
 1072                 else:
 1073                     if self.ui.currentProg is None:
 1074                         self.appendStdout.emit(self.tr(
 1075                             'The program has terminated with an exit status'
 1076                             ' of {0}.\n{1}\n').format(status, info))
 1077                     else:
 1078                         self.appendStdout.emit(self.tr(
 1079                             '"{0}" has terminated with an exit status of'
 1080                             ' {1}.\n{2}\n').format(
 1081                             Utilities.normabspath(self.ui.currentProg), status,
 1082                             info))
 1083 
 1084     def __clientSyntaxError(self, message, filename, lineNo, characterNo):
 1085         """
 1086         Private method to handle a syntax error in the debugged program.
 1087         
 1088         @param message message of the syntax error (string)
 1089         @param filename translated filename of the syntax error position
 1090             (string)
 1091         @param lineNo line number of the syntax error position (integer)
 1092         @param characterNo character number of the syntax error position
 1093             (integer)
 1094         """
 1095         self.__resetUI()
 1096         self.ui.raise_()
 1097         self.ui.activateWindow()
 1098         
 1099         if message is None:
 1100             E5MessageBox.critical(
 1101                 self.ui, Program,
 1102                 self.tr(
 1103                     'The program being debugged contains an unspecified'
 1104                     ' syntax error.'))
 1105             return
 1106             
 1107         if not os.path.isabs(filename):
 1108             if os.path.exists(os.path.join(self.project.getProjectPath(),
 1109                               filename)):
 1110                 filename = os.path.join(self.project.getProjectPath(),
 1111                                         filename)
 1112             else:
 1113                 ms = self.project.getMainScript(normalized=True)
 1114                 if ms is not None:
 1115                     d = os.path.dirname(ms)
 1116                     if os.path.exists(os.path.join(d, filename)):
 1117                         filename = os.path.join(d, filename)
 1118         self.viewmanager.setFileLine(filename, lineNo, True, True)
 1119         E5MessageBox.critical(
 1120             self.ui, Program,
 1121             self.tr('<p>The file <b>{0}</b> contains the syntax error'
 1122                     ' <b>{1}</b> at line <b>{2}</b>, character <b>{3}</b>.'
 1123                     '</p>')
 1124                 .format(filename, message, lineNo, characterNo))
 1125         
 1126     def __clientException(self, exceptionType, exceptionMessage, stackTrace):
 1127         """
 1128         Private method to handle an exception of the debugged program.
 1129         
 1130         @param exceptionType type of exception raised (string)
 1131         @param exceptionMessage message given by the exception (string)
 1132         @param stackTrace list of stack entries (list of string)
 1133         """
 1134         self.ui.raise_()
 1135         QApplication.processEvents()
 1136         if not exceptionType:
 1137             E5MessageBox.critical(
 1138                 self.ui, Program,
 1139                 self.tr('An unhandled exception occured.'
 1140                         ' See the shell window for details.'))
 1141             return
 1142         
 1143         if (
 1144             (self.exceptions and
 1145              exceptionType not in self.excIgnoreList and
 1146              (not len(self.excList) or
 1147               (len(self.excList) and exceptionType in self.excList)
 1148               )
 1149              ) or exceptionType.startswith('unhandled')
 1150         ):
 1151             res = None
 1152             if stackTrace:
 1153                 try:
 1154                     file, line = stackTrace[0][:2]
 1155                     source, encoding = Utilities.readEncodedFile(file)
 1156                     source = source.splitlines(True)
 1157                     if len(source) >= line:
 1158                         lineFlags = Utilities.extractLineFlags(
 1159                             source[line - 1].strip())
 1160                         try:
 1161                             lineFlags += Utilities.extractLineFlags(
 1162                                 source[line].strip(), flagsLine=True)
 1163                         except IndexError:
 1164                             pass
 1165                         if "__IGNORE_EXCEPTION__" in lineFlags:
 1166                             res = E5MessageBox.No
 1167                 except (UnicodeError, IOError):
 1168                     pass
 1169                 if res != E5MessageBox.No:
 1170                     self.viewmanager.setFileLine(
 1171                         stackTrace[0][0], stackTrace[0][1], True)
 1172             if res != E5MessageBox.No:
 1173                 self.ui.activateWindow()
 1174                 if Preferences.getDebugger("BreakAlways"):
 1175                     res = E5MessageBox.Yes
 1176                 else:
 1177                     if stackTrace:
 1178                         if exceptionType.startswith('unhandled'):
 1179                             buttons = E5MessageBox.StandardButtons(
 1180                                 E5MessageBox.No |
 1181                                 E5MessageBox.Yes)
 1182                         else:
 1183                             buttons = E5MessageBox.StandardButtons(
 1184                                 E5MessageBox.No |
 1185                                 E5MessageBox.Yes |
 1186                                 E5MessageBox.Ignore)
 1187                         res = E5MessageBox.critical(
 1188                             self.ui, Program,
 1189                             self.tr(
 1190                                 '<p>The debugged program raised the exception'
 1191                                 ' <b>{0}</b><br>"<b>{1}</b>"<br>'
 1192                                 'File: <b>{2}</b>, Line: <b>{3}</b></p>'
 1193                                 '<p>Break here?</p>')
 1194                             .format(
 1195                                 exceptionType,
 1196                                 Utilities.html_encode(exceptionMessage),
 1197                                 stackTrace[0][0],
 1198                                 stackTrace[0][1]),
 1199                             buttons,
 1200                             E5MessageBox.No)
 1201                     else:
 1202                         res = E5MessageBox.critical(
 1203                             self.ui, Program,
 1204                             self.tr(
 1205                                 '<p>The debugged program raised the exception'
 1206                                 ' <b>{0}</b><br>"<b>{1}</b>"</p>')
 1207                             .format(
 1208                                 exceptionType,
 1209                                 Utilities.html_encode(exceptionMessage)))
 1210             if res == E5MessageBox.Yes:
 1211                 self.debugServer.setDebugging(True)
 1212                 self.exceptionInterrupt.emit()
 1213                 stack = []
 1214                 for fn, ln, func, args in stackTrace:
 1215                     stack.append((fn, ln, func, args))
 1216                 self.clientStack.emit(stack)
 1217                 self.__getClientVariables()
 1218                 self.ui.setDebugProfile()
 1219                 self.debugActGrp.setEnabled(True)
 1220                 return
 1221             elif res == E5MessageBox.Ignore:
 1222                 if exceptionType not in self.excIgnoreList:
 1223                     self.excIgnoreList.append(exceptionType)
 1224         
 1225         if self.lastAction != -1:
 1226             if self.lastAction == 2:
 1227                 self.__specialContinue()
 1228             else:
 1229                 self.debugActions[self.lastAction]()
 1230         else:
 1231             self.__continue()
 1232         
 1233     def __clientSignal(self, message, filename, lineNo, funcName, funcArgs):
 1234         """
 1235         Private method to handle a signal generated on the client side.
 1236         
 1237         @param message message of the syntax error
 1238         @type str
 1239         @param filename translated filename of the syntax error position
 1240         @type str
 1241         @param lineNo line number of the syntax error position
 1242         @type int
 1243         @param funcName name of the function causing the signal
 1244         @type str
 1245         @param funcArgs function arguments
 1246         @type str
 1247         """
 1248         self.ui.raise_()
 1249         self.ui.activateWindow()
 1250         QApplication.processEvents()
 1251         self.viewmanager.setFileLine(filename, lineNo, True)
 1252         E5MessageBox.critical(
 1253             self.ui, Program,
 1254             self.tr("""<p>The program generate the signal "{0}".<br/>"""
 1255                     """File: <b>{1}</b>, Line: <b>{2}</b></p>""").format(
 1256                 message, filename, lineNo))
 1257         
 1258     def __clientGone(self, unplanned):
 1259         """
 1260         Private method to handle the disconnection of the debugger client.
 1261         
 1262         @param unplanned True if the client died, False otherwise
 1263         """
 1264         self.__resetUI()
 1265         if unplanned:
 1266             E5MessageBox.information(
 1267                 self.ui, Program,
 1268                 self.tr('The program being debugged has terminated'
 1269                         ' unexpectedly.'))
 1270         
 1271     def __getThreadList(self):
 1272         """
 1273         Private method to get the list of threads from the client.
 1274         """
 1275         self.debugServer.remoteThreadList()
 1276         
 1277     def __clientThreadSet(self):
 1278         """
 1279         Private method to handle a change of the client's current thread.
 1280         """
 1281         self.debugServer.remoteClientVariables(0, self.localsVarFilter)
 1282         
 1283     def __getClientVariables(self):
 1284         """
 1285         Private method to request the global and local variables.
 1286         
 1287         In the first step, the global variables are requested from the client.
 1288         Once these have been received, the local variables are requested.
 1289         This happens in the method '__clientVariables'.
 1290         """
 1291         # get globals first
 1292         self.debugServer.remoteClientVariables(1, self.globalsVarFilter)
 1293         # the local variables are requested once we have received the globals
 1294         
 1295     def __clientVariables(self, scope, variables):
 1296         """
 1297         Private method to write the clients variables to the user interface.
 1298         
 1299         @param scope scope of the variables (-1 = empty global, 1 = global,
 1300             0 = local)
 1301         @param variables the list of variables from the client
 1302         """
 1303         self.ui.activateDebugViewer()
 1304         if scope > 0:
 1305             self.debugViewer.showVariables(variables, True)
 1306             if scope == 1:
 1307                 # now get the local variables
 1308                 self.debugServer.remoteClientVariables(0, self.localsVarFilter)
 1309         elif scope == 0:
 1310             self.debugViewer.showVariables(variables, False)
 1311         elif scope == -1:
 1312             vlist = [(self.tr('No locals available.'), '', '')]
 1313             self.debugViewer.showVariables(vlist, False)
 1314         
 1315     def __clientVariable(self, scope, variables):
 1316         """
 1317         Private method to write the contents of a clients classvariable to
 1318         the user interface.
 1319         
 1320         @param scope scope of the variables (-1 = empty global, 1 = global,
 1321             0 = local)
 1322         @param variables the list of members of a classvariable from the client
 1323         """
 1324         self.ui.activateDebugViewer()
 1325         if scope == 1:
 1326             self.debugViewer.showVariable(variables, True)
 1327         elif scope == 0:
 1328             self.debugViewer.showVariable(variables, False)
 1329             
 1330     def __clientBreakConditionError(self, filename, lineno):
 1331         """
 1332         Private method to handle a condition error of a breakpoint.
 1333         
 1334         @param filename filename of the breakpoint (string)
 1335         @param lineno linenumber of the breakpoint (integer)
 1336         """
 1337         E5MessageBox.critical(
 1338             self.ui,
 1339             self.tr("Breakpoint Condition Error"),
 1340             self.tr(
 1341                 """<p>The condition of the breakpoint <b>{0}, {1}</b>"""
 1342                 """ contains a syntax error.</p>""")
 1343             .format(filename, lineno))
 1344         
 1345         model = self.debugServer.getBreakPointModel()
 1346         index = model.getBreakPointIndex(filename, lineno)
 1347         if not index.isValid():
 1348             return
 1349         
 1350         bp = model.getBreakPointByIndex(index)
 1351         if not bp:
 1352             return
 1353         
 1354         fn, line, cond, temp, enabled, count = bp[:6]
 1355         
 1356         from .EditBreakpointDialog import EditBreakpointDialog
 1357         dlg = EditBreakpointDialog(
 1358             (fn, line), (cond, temp, enabled, count),
 1359             [], self.ui, modal=True)
 1360         if dlg.exec_() == QDialog.Accepted:
 1361             cond, temp, enabled, count = dlg.getData()
 1362             model.setBreakPointByIndex(index, fn, line,
 1363                                        (cond, temp, enabled, count))
 1364         
 1365     def __clientWatchConditionError(self, cond):
 1366         """
 1367         Private method to handle a expression error of a watch expression.
 1368         
 1369         Note: This can only happen for normal watch expressions
 1370         
 1371         @param cond expression of the watch expression (string)
 1372         """
 1373         E5MessageBox.critical(
 1374             self.ui,
 1375             self.tr("Watch Expression Error"),
 1376             self.tr("""<p>The watch expression <b>{0}</b>"""
 1377                     """ contains a syntax error.</p>""")
 1378             .format(cond))
 1379         
 1380         model = self.debugServer.getWatchPointModel()
 1381         index = model.getWatchPointIndex(cond)
 1382         if not index.isValid():
 1383             return
 1384         
 1385         wp = model.getWatchPointByIndex(index)
 1386         if not wp:
 1387             return
 1388         
 1389         cond, special, temp, enabled, count = wp[:5]
 1390         
 1391         from .EditWatchpointDialog import EditWatchpointDialog
 1392         dlg = EditWatchpointDialog(
 1393             (cond, temp, enabled, count, special), self.ui)
 1394         if dlg.exec_() == QDialog.Accepted:
 1395             cond, temp, enabled, count, special = dlg.getData()
 1396             
 1397             # check for duplicates
 1398             idx = model.getWatchPointIndex(cond, special)
 1399             duplicate = (idx.isValid() and
 1400                          idx.internalPointer() != index.internalPointer())
 1401             if duplicate:
 1402                 if not special:
 1403                     msg = self.tr(
 1404                         """<p>A watch expression '<b>{0}</b>'"""
 1405                         """ already exists.</p>"""
 1406                     ).format(Utilities.html_encode(cond))
 1407                 else:
 1408                     msg = self.tr(
 1409                         """<p>A watch expression '<b>{0}</b>'"""
 1410                         """ for the variable <b>{1}</b> already"""
 1411                         """ exists.</p>"""
 1412                     ).format(special, Utilities.html_encode(cond))
 1413                 E5MessageBox.warning(
 1414                     self.ui,
 1415                     self.tr("Watch expression already exists"),
 1416                     msg)
 1417                 model.deleteWatchPointByIndex(index)
 1418             else:
 1419                 model.setWatchPointByIndex(index, cond, special,
 1420                                            (temp, enabled, count))
 1421         
 1422     def __configureVariablesFilters(self):
 1423         """
 1424         Private slot for displaying the variables filter configuration dialog.
 1425         """
 1426         from .VariablesFilterDialog import VariablesFilterDialog
 1427         dlg = VariablesFilterDialog(self.ui, 'Filter Dialog', True)
 1428         dlg.setSelection(self.localsVarFilter, self.globalsVarFilter)
 1429         if dlg.exec_() == QDialog.Accepted:
 1430             self.localsVarFilter, self.globalsVarFilter = dlg.getSelection()
 1431             self.debugViewer.setVariablesFilter(
 1432                 self.globalsVarFilter, self.localsVarFilter)
 1433 
 1434     def __configureExceptionsFilter(self):
 1435         """
 1436         Private slot for displaying the exception filter dialog.
 1437         """
 1438         from .ExceptionsFilterDialog import ExceptionsFilterDialog
 1439         dlg = ExceptionsFilterDialog(self.excList, ignore=False)
 1440         if dlg.exec_() == QDialog.Accepted:
 1441             self.excList = dlg.getExceptionsList()[:]   # keep a copy
 1442         
 1443     def __configureIgnoredExceptions(self):
 1444         """
 1445         Private slot for displaying the ignored exceptions dialog.
 1446         """
 1447         from .ExceptionsFilterDialog import ExceptionsFilterDialog
 1448         dlg = ExceptionsFilterDialog(self.excIgnoreList, ignore=True)
 1449         if dlg.exec_() == QDialog.Accepted:
 1450             self.excIgnoreList = dlg.getExceptionsList()[:]   # keep a copy
 1451         
 1452     def __toggleBreakpoint(self):
 1453         """
 1454         Private slot to handle the 'Set/Reset breakpoint' action.
 1455         """
 1456         self.viewmanager.activeWindow().menuToggleBreakpoint()
 1457         
 1458     def __editBreakpoint(self):
 1459         """
 1460         Private slot to handle the 'Edit breakpoint' action.
 1461         """
 1462         self.viewmanager.activeWindow().menuEditBreakpoint()
 1463         
 1464     def __nextBreakpoint(self):
 1465         """
 1466         Private slot to handle the 'Next breakpoint' action.
 1467         """
 1468         self.viewmanager.activeWindow().menuNextBreakpoint()
 1469         
 1470     def __previousBreakpoint(self):
 1471         """
 1472         Private slot to handle the 'Previous breakpoint' action.
 1473         """
 1474         self.viewmanager.activeWindow().menuPreviousBreakpoint()
 1475         
 1476     def __clearBreakpoints(self):
 1477         """
 1478         Private slot to handle the 'Clear breakpoints' action.
 1479         """
 1480         self.debugServer.getBreakPointModel().deleteAll()
 1481         
 1482     def __showDebugMenu(self):
 1483         """
 1484         Private method to set up the debug menu.
 1485         """
 1486         bpCount = self.debugServer.getBreakPointModel().rowCount()
 1487         self.menuBreakpointsAct.setEnabled(bpCount > 0)
 1488         
 1489     def __showBreakpointsMenu(self):
 1490         """
 1491         Private method to handle the show breakpoints menu signal.
 1492         """
 1493         self.breakpointsMenu.clear()
 1494         
 1495         model = self.debugServer.getBreakPointModel()
 1496         for row in range(model.rowCount()):
 1497             index = model.index(row, 0)
 1498             filename, line, cond = model.getBreakPointByIndex(index)[:3]
 1499             if not cond:
 1500                 formattedCond = ""
 1501             else:
 1502                 formattedCond = " : {0}".format(cond[:20])
 1503             bpSuffix = " : {0:d}{1}".format(line, formattedCond)
 1504             act = self.breakpointsMenu.addAction(
 1505                 "{0}{1}".format(
 1506                     Utilities.compactPath(
 1507                         filename,
 1508                         self.ui.maxMenuFilePathLen - len(bpSuffix)),
 1509                     bpSuffix))
 1510             act.setData([filename, line])
 1511     
 1512     def __breakpointSelected(self, act):
 1513         """
 1514         Private method to handle the breakpoint selected signal.
 1515         
 1516         @param act reference to the action that triggered (QAction)
 1517         """
 1518         qvList = act.data()
 1519         filename = qvList[0]
 1520         line = qvList[1]
 1521         self.viewmanager.openSourceFile(filename, line)
 1522         
 1523     def __compileChangedProjectFiles(self):
 1524         """
 1525         Private method to signal compilation of changed forms and resources
 1526         is wanted.
 1527         """
 1528         if Preferences.getProject("AutoCompileForms"):
 1529             self.compileForms.emit()
 1530         if Preferences.getProject("AutoCompileResources"):
 1531             self.compileResources.emit()
 1532         if Preferences.getProject("AutoExecuteMake"):
 1533             self.executeMake.emit()
 1534         QApplication.processEvents()
 1535         
 1536     def __coverageScript(self):
 1537         """
 1538         Private slot to handle the coverage of script action.
 1539         """
 1540         self.__doCoverage(False)
 1541         
 1542     def __coverageProject(self):
 1543         """
 1544         Private slot to handle the coverage of project action.
 1545         """
 1546         self.__compileChangedProjectFiles()
 1547         self.__doCoverage(True)
 1548         
 1549     def __doCoverage(self, runProject):
 1550         """
 1551         Private method to handle the coverage actions.
 1552         
 1553         @param runProject flag indicating coverage of the current project
 1554             (True) or script (false)
 1555         """
 1556         from .StartDialog import StartDialog
 1557         
 1558         self.__resetUI()
 1559         doNotStart = False
 1560         
 1561         # Get the command line arguments, the working directory and the
 1562         # exception reporting flag.
 1563         if runProject:
 1564             cap = self.tr("Coverage of Project")
 1565         else:
 1566             cap = self.tr("Coverage of Script")
 1567         dlg = StartDialog(
 1568             cap, self.lastUsedVenvName, self.argvHistory, self.wdHistory,
 1569             self.envHistory, self.exceptions, self.ui, 2,
 1570             autoClearShell=self.autoClearShell)
 1571         if dlg.exec_() == QDialog.Accepted:
 1572             (lastUsedVenvName, argv, wd, env, exceptions, clearShell,
 1573              console) = dlg.getData()
 1574             eraseCoverage = dlg.getCoverageData()
 1575             
 1576             if runProject:
 1577                 fn = self.project.getMainScript(True)
 1578                 if fn is None:
 1579                     E5MessageBox.critical(
 1580                         self.ui,
 1581                         self.tr("Coverage of Project"),
 1582                         self.tr(
 1583                             "There is no main script defined for the"
 1584                             " current project. Aborting"))
 1585                     return
 1586                     
 1587                 if (
 1588                     Preferences.getDebugger("Autosave") and
 1589                     not self.project.saveAllScripts(reportSyntaxErrors=True)
 1590                 ):
 1591                     doNotStart = True
 1592                 
 1593                 # save the info for later use
 1594                 self.project.setDbgInfo(
 1595                     lastUsedVenvName, argv, wd, env, exceptions, self.excList,
 1596                     self.excIgnoreList, clearShell)
 1597                 
 1598                 self.lastStartAction = 6
 1599                 self.clientType = self.project.getProjectLanguage()
 1600             else:
 1601                 editor = self.viewmanager.activeWindow()
 1602                 if editor is None:
 1603                     return
 1604                 
 1605                 if (
 1606                     not self.viewmanager.checkDirty(
 1607                         editor, Preferences.getDebugger("Autosave")) or
 1608                     editor.getFileName() is None
 1609                 ):
 1610                     return
 1611                     
 1612                 fn = editor.getFileName()
 1613                 self.lastStartAction = 5
 1614                 self.clientType = editor.determineFileType()
 1615                 
 1616             # save the filename for use by the restart method
 1617             self.lastDebuggedFile = fn
 1618             self.restartAct.setEnabled(True)
 1619             
 1620             # save the most recently used virtual environment
 1621             self.lastUsedVenvName = lastUsedVenvName
 1622             
 1623             # This moves any previous occurrence of these arguments to the head
 1624             # of the list.
 1625             self.setArgvHistory(argv)
 1626             self.setWdHistory(wd)
 1627             self.setEnvHistory(env)
 1628             
 1629             # Save the exception flags
 1630             self.exceptions = exceptions
 1631             
 1632             # Save the erase coverage flag
 1633             self.eraseCoverage = eraseCoverage
 1634             
 1635             # Save the clear interpreter flag
 1636             self.autoClearShell = clearShell
 1637             
 1638             # Save the run in console flag
 1639             self.runInConsole = console
 1640             
 1641             # Hide all error highlights
 1642             self.viewmanager.unhighlight()
 1643             
 1644             if not doNotStart:
 1645                 if runProject and self.project.getProjectType() in [
 1646                         "E6Plugin"]:
 1647                     argv = '--plugin="{0}" {1}'.format(fn, argv)
 1648                     fn = os.path.join(getConfig('ericDir'), "eric6.py")
 1649                 
 1650                 self.debugViewer.initCallStackViewer(runProject)
 1651                 
 1652                 # Ask the client to open the new program.
 1653                 self.debugServer.remoteCoverage(
 1654                     lastUsedVenvName, fn, argv, wd, env,
 1655                     autoClearShell=self.autoClearShell, erase=eraseCoverage,
 1656                     forProject=runProject, runInConsole=console,
 1657                     clientType=self.clientType)
 1658                 
 1659                 self.stopAct.setEnabled(True)
 1660         
 1661         if dlg.clearHistories():
 1662             self.setArgvHistory("", clearHistories=True)
 1663             self.setWdHistory("", clearHistories=True)
 1664             self.setEnvHistory("", clearHistories=True)
 1665         elif dlg.historiesModified():
 1666             argvHistory, wdHistory, envHistory = dlg.getHistories()
 1667             self.setArgvHistory("", history=argvHistory)
 1668             self.setWdHistory("", history=wdHistory)
 1669             self.setEnvHistory("", history=envHistory)
 1670     
 1671     def __profileScript(self):
 1672         """
 1673         Private slot to handle the profile script action.
 1674         """
 1675         self.__doProfile(False)
 1676         
 1677     def __profileProject(self):
 1678         """
 1679         Private slot to handle the profile project action.
 1680         """
 1681         self.__compileChangedProjectFiles()
 1682         self.__doProfile(True)
 1683         
 1684     def __doProfile(self, runProject):
 1685         """
 1686         Private method to handle the profile actions.
 1687         
 1688         @param runProject flag indicating profiling of the current project
 1689             (True) or script (False)
 1690         """
 1691         from .StartDialog import StartDialog
 1692         
 1693         self.__resetUI()
 1694         doNotStart = False
 1695         
 1696         # Get the command line arguments, the working directory and the
 1697         # exception reporting flag.
 1698         if runProject:
 1699             cap = self.tr("Profile of Project")
 1700         else:
 1701             cap = self.tr("Profile of Script")
 1702         dlg = StartDialog(
 1703             cap, self.lastUsedVenvName, self.argvHistory, self.wdHistory,
 1704             self.envHistory, self.exceptions, self.ui, 3,
 1705             autoClearShell=self.autoClearShell)
 1706         if dlg.exec_() == QDialog.Accepted:
 1707             (lastUsedVenvName, argv, wd, env, exceptions, clearShell,
 1708              console) = dlg.getData()
 1709             eraseTimings = dlg.getProfilingData()
 1710             
 1711             if runProject:
 1712                 fn = self.project.getMainScript(True)
 1713                 if fn is None:
 1714                     E5MessageBox.critical(
 1715                         self.ui,
 1716                         self.tr("Profile of Project"),
 1717                         self.tr(
 1718                             "There is no main script defined for the"
 1719                             " current project. Aborting"))
 1720                     return
 1721                     
 1722                 if (
 1723                     Preferences.getDebugger("Autosave") and
 1724                     not self.project.saveAllScripts(reportSyntaxErrors=True)
 1725                 ):
 1726                     doNotStart = True
 1727                 
 1728                 # save the info for later use
 1729                 self.project.setDbgInfo(
 1730                     lastUsedVenvName, argv, wd, env, exceptions, self.excList,
 1731                     self.excIgnoreList, clearShell)
 1732                 
 1733                 self.lastStartAction = 8
 1734                 self.clientType = self.project.getProjectLanguage()
 1735             else:
 1736                 editor = self.viewmanager.activeWindow()
 1737                 if editor is None:
 1738                     return
 1739                 
 1740                 if (
 1741                     not self.viewmanager.checkDirty(
 1742                         editor, Preferences.getDebugger("Autosave")) or
 1743                     editor.getFileName() is None
 1744                 ):
 1745                     return
 1746                     
 1747                 fn = editor.getFileName()
 1748                 self.lastStartAction = 7
 1749                 self.clientType = editor.determineFileType()
 1750                 
 1751             # save the filename for use by the restart method
 1752             self.lastDebuggedFile = fn
 1753             self.restartAct.setEnabled(True)
 1754             
 1755             # save the most recently used virtual environment
 1756             self.lastUsedVenvName = lastUsedVenvName
 1757             
 1758             # This moves any previous occurrence of these arguments to the head
 1759             # of the list.
 1760             self.setArgvHistory(argv)
 1761             self.setWdHistory(wd)
 1762             self.setEnvHistory(env)
 1763             
 1764             # Save the exception flags
 1765             self.exceptions = exceptions
 1766             
 1767             # Save the erase timing flag
 1768             self.eraseTimings = eraseTimings
 1769             
 1770             # Save the clear interpreter flag
 1771             self.autoClearShell = clearShell
 1772             
 1773             # Save the run in console flag
 1774             self.runInConsole = console
 1775             
 1776             # Hide all error highlights
 1777             self.viewmanager.unhighlight()
 1778             
 1779             if not doNotStart:
 1780                 if runProject and self.project.getProjectType() in [
 1781                         "E6Plugin"]:
 1782                     argv = '--plugin="{0}" {1}'.format(fn, argv)
 1783                     fn = os.path.join(getConfig('ericDir'), "eric6.py")
 1784                 
 1785                 self.debugViewer.initCallStackViewer(runProject)
 1786                 
 1787                 # Ask the client to open the new program.
 1788                 self.debugServer.remoteProfile(
 1789                     lastUsedVenvName, fn, argv, wd, env,
 1790                     autoClearShell=self.autoClearShell, erase=eraseTimings,
 1791                     forProject=runProject, runInConsole=console,
 1792                     clientType=self.clientType)
 1793                 
 1794                 self.stopAct.setEnabled(True)
 1795         
 1796         if dlg.clearHistories():
 1797             self.setArgvHistory("", clearHistories=True)
 1798             self.setWdHistory("", clearHistories=True)
 1799             self.setEnvHistory("", clearHistories=True)
 1800         elif dlg.historiesModified():
 1801             argvHistory, wdHistory, envHistory = dlg.getHistories()
 1802             self.setArgvHistory("", history=argvHistory)
 1803             self.setWdHistory("", history=wdHistory)
 1804             self.setEnvHistory("", history=envHistory)
 1805     
 1806     def __runScript(self):
 1807         """
 1808         Private slot to handle the run script action.
 1809         """
 1810         self.__doRun(False)
 1811         
 1812     def __runProject(self):
 1813         """
 1814         Private slot to handle the run project action.
 1815         """
 1816         self.__compileChangedProjectFiles()
 1817         self.__doRun(True)
 1818         
 1819     def __doRun(self, runProject):
 1820         """
 1821         Private method to handle the run actions.
 1822         
 1823         @param runProject flag indicating running the current project (True)
 1824                 or script (False)
 1825         """
 1826         from .StartDialog import StartDialog
 1827         
 1828         self.__resetUI()
 1829         doNotStart = False
 1830         
 1831         # Get the command line arguments, the working directory and the
 1832         # exception reporting flag.
 1833         if runProject:
 1834             cap = self.tr("Run Project")
 1835         else:
 1836             cap = self.tr("Run Script")
 1837         dlg = StartDialog(
 1838             cap, self.lastUsedVenvName, self.argvHistory, self.wdHistory,
 1839             self.envHistory, self.exceptions, self.ui, 1,
 1840             autoClearShell=self.autoClearShell,
 1841             autoFork=self.forkAutomatically,
 1842             forkChild=self.forkIntoChild)
 1843         if dlg.exec_() == QDialog.Accepted:
 1844             (lastUsedVenvName, argv, wd, env, exceptions, clearShell,
 1845              console) = dlg.getData()
 1846             forkAutomatically, forkIntoChild = dlg.getRunData()
 1847             
 1848             if runProject:
 1849                 fn = self.project.getMainScript(True)
 1850                 if fn is None:
 1851                     E5MessageBox.critical(
 1852                         self.ui,
 1853                         self.tr("Run Project"),
 1854                         self.tr(
 1855                             "There is no main script defined for the"
 1856                             " current project. Aborting"))
 1857                     return
 1858                     
 1859                 if (
 1860                     Preferences.getDebugger("Autosave") and
 1861                     not self.project.saveAllScripts(reportSyntaxErrors=True)
 1862                 ):
 1863                     doNotStart = True
 1864                 
 1865                 # save the info for later use
 1866                 self.project.setDbgInfo(
 1867                     lastUsedVenvName, argv, wd, env, exceptions, self.excList,
 1868                     self.excIgnoreList, clearShell)
 1869                 
 1870                 self.lastStartAction = 4
 1871                 self.clientType = self.project.getProjectLanguage()
 1872             else:
 1873                 editor = self.viewmanager.activeWindow()
 1874                 if editor is None:
 1875                     return
 1876                 
 1877                 if (
 1878                     not self.viewmanager.checkDirty(
 1879                         editor,
 1880                         Preferences.getDebugger("Autosave")) or
 1881                     editor.getFileName() is None
 1882                 ):
 1883                     return
 1884                     
 1885                 fn = editor.getFileName()
 1886                 self.lastStartAction = 3
 1887                 self.clientType = editor.determineFileType()
 1888                 
 1889             # save the filename for use by the restart method
 1890             self.lastDebuggedFile = fn
 1891             self.restartAct.setEnabled(True)
 1892             
 1893             # save the most recently used virtual environment
 1894             self.lastUsedVenvName = lastUsedVenvName
 1895             
 1896             # This moves any previous occurrence of these arguments to the head
 1897             # of the list.
 1898             self.setArgvHistory(argv)
 1899             self.setWdHistory(wd)
 1900             self.setEnvHistory(env)
 1901             
 1902             # Save the exception flags
 1903             self.exceptions = exceptions
 1904             
 1905             # Save the clear interpreter flag
 1906             self.autoClearShell = clearShell
 1907             
 1908             # Save the run in console flag
 1909             self.runInConsole = console
 1910             
 1911             # Save the forking flags
 1912             self.forkAutomatically = forkAutomatically
 1913             self.forkIntoChild = forkIntoChild
 1914             
 1915             # Hide all error highlights
 1916             self.viewmanager.unhighlight()
 1917             
 1918             if not doNotStart:
 1919                 if runProject and self.project.getProjectType() in [
 1920                         "E6Plugin"]:
 1921                     argv = '--plugin="{0}" {1}'.format(fn, argv)
 1922                     fn = os.path.join(getConfig('ericDir'), "eric6.py")
 1923                 
 1924                 self.debugViewer.initCallStackViewer(runProject)
 1925                 
 1926                 # Ask the client to open the new program.
 1927                 self.debugServer.remoteRun(
 1928                     lastUsedVenvName, fn, argv, wd, env,
 1929                     autoClearShell=self.autoClearShell, forProject=runProject,
 1930                     runInConsole=console, autoFork=forkAutomatically,
 1931                     forkChild=forkIntoChild, clientType=self.clientType)
 1932                 
 1933                 self.stopAct.setEnabled(True)
 1934         
 1935         if dlg.clearHistories():
 1936             self.setArgvHistory("", clearHistories=True)
 1937             self.setWdHistory("", clearHistories=True)
 1938             self.setEnvHistory("", clearHistories=True)
 1939         elif dlg.historiesModified():
 1940             argvHistory, wdHistory, envHistory = dlg.getHistories()
 1941             self.setArgvHistory("", history=argvHistory)
 1942             self.setWdHistory("", history=wdHistory)
 1943             self.setEnvHistory("", history=envHistory)
 1944     
 1945     def __debugScript(self):
 1946         """
 1947         Private slot to handle the debug script action.
 1948         """
 1949         self.__doDebug(False)
 1950         
 1951     def __debugProject(self):
 1952         """
 1953         Private slot to handle the debug project action.
 1954         """
 1955         self.__compileChangedProjectFiles()
 1956         self.__doDebug(True)
 1957         
 1958     def __doDebug(self, debugProject):
 1959         """
 1960         Private method to handle the debug actions.
 1961         
 1962         @param debugProject flag indicating debugging the current project
 1963             (True) or script (False)
 1964         """
 1965         from .StartDialog import StartDialog
 1966         
 1967         self.__resetUI()
 1968         doNotStart = False
 1969         
 1970         # Get the command line arguments, the working directory and the
 1971         # exception reporting flag.
 1972         if debugProject:
 1973             cap = self.tr("Debug Project")
 1974         else:
 1975             cap = self.tr("Debug Script")
 1976         dlg = StartDialog(
 1977             cap, self.lastUsedVenvName, self.argvHistory, self.wdHistory,
 1978             self.envHistory, self.exceptions, self.ui, 0,
 1979             tracePython=self.tracePython, autoClearShell=self.autoClearShell,
 1980             autoContinue=self.autoContinue, autoFork=self.forkAutomatically,
 1981             forkChild=self.forkIntoChild)
 1982         if dlg.exec_() == QDialog.Accepted:
 1983             (lastUsedVenvName, argv, wd, env, exceptions, clearShell,
 1984              console) = dlg.getData()
 1985             tracePython, autoContinue, forkAutomatically, forkIntoChild = (
 1986                 dlg.getDebugData())
 1987             
 1988             if debugProject:
 1989                 fn = self.project.getMainScript(True)
 1990                 if fn is None:
 1991                     E5MessageBox.critical(
 1992                         self.ui,
 1993                         self.tr("Debug Project"),
 1994                         self.tr(
 1995                             "There is no main script defined for the"
 1996                             " current project. No debugging possible."))
 1997                     return
 1998                     
 1999                 if (
 2000                     Preferences.getDebugger("Autosave") and
 2001                     not self.project.saveAllScripts(reportSyntaxErrors=True)
 2002                 ):
 2003                     doNotStart = True
 2004                 
 2005                 # save the info for later use
 2006                 self.project.setDbgInfo(
 2007                     lastUsedVenvName, argv, wd, env, exceptions, self.excList,
 2008                     self.excIgnoreList, clearShell, tracePython=tracePython,
 2009                     autoContinue=self.autoContinue)
 2010                 
 2011                 self.lastStartAction = 2
 2012                 self.clientType = self.project.getProjectLanguage()
 2013             else:
 2014                 editor = self.viewmanager.activeWindow()
 2015                 if editor is None:
 2016                     return
 2017                 
 2018                 if (
 2019                     not self.viewmanager.checkDirty(
 2020                         editor, Preferences.getDebugger("Autosave")) or
 2021                     editor.getFileName() is None
 2022                 ):
 2023                     return
 2024                     
 2025                 fn = editor.getFileName()
 2026                 self.lastStartAction = 1
 2027                 self.clientType = editor.determineFileType()
 2028             
 2029             # save the filename for use by the restart method
 2030             self.lastDebuggedFile = fn
 2031             self.restartAct.setEnabled(True)
 2032             
 2033             # save the most recently used virtual environment
 2034             self.lastUsedVenvName = lastUsedVenvName
 2035             
 2036             # This moves any previous occurrence of these arguments to the head
 2037             # of the list.
 2038             self.setArgvHistory(argv)
 2039             self.setWdHistory(wd)
 2040             self.setEnvHistory(env)
 2041             
 2042             # Save the exception flags
 2043             self.exceptions = exceptions
 2044             
 2045             # Save the tracePython flag
 2046             self.tracePython = tracePython
 2047             
 2048             # Save the clear interpreter flag
 2049             self.autoClearShell = clearShell
 2050             
 2051             # Save the run in console flag
 2052             self.runInConsole = console
 2053             
 2054             # Save the auto continue flag
 2055             self.autoContinue = autoContinue
 2056             
 2057             # Save the forking flags
 2058             self.forkAutomatically = forkAutomatically
 2059             self.forkIntoChild = forkIntoChild
 2060             
 2061             # Hide all error highlights
 2062             self.viewmanager.unhighlight()
 2063             
 2064             if not doNotStart:
 2065                 if debugProject and self.project.getProjectType() in [
 2066                         "E6Plugin"]:
 2067                     argv = '--plugin="{0}" {1}'.format(fn, argv)
 2068                     fn = os.path.join(getConfig('ericDir'), "eric6.py")
 2069                     tracePython = True  # override flag because it must be true
 2070                 
 2071                 self.debugViewer.initCallStackViewer(debugProject)
 2072                 
 2073                 # Ask the client to send call trace info
 2074                 enableCallTrace = self.debugViewer.isCallTraceEnabled()
 2075                 self.debugViewer.clearCallTrace()
 2076                 self.debugViewer.setCallTraceToProjectMode(debugProject)
 2077                 
 2078                 # Ask the client to open the new program.
 2079                 self.debugServer.remoteLoad(
 2080                     lastUsedVenvName, fn, argv, wd, env,
 2081                     autoClearShell=self.autoClearShell,
 2082                     tracePython=tracePython,
 2083                     autoContinue=autoContinue, forProject=debugProject,
 2084                     runInConsole=console, autoFork=forkAutomatically,
 2085                     forkChild=forkIntoChild, clientType=self.clientType,
 2086                     enableCallTrace=enableCallTrace)
 2087                 
 2088                 if (
 2089                     self.debugServer.isClientProcessUp() and
 2090                     self.debugServer.getClientType() == self.clientType
 2091                 ):
 2092                     # Signal that we have started a debugging session
 2093                     self.debuggingStarted.emit(fn)
 2094                     
 2095                     self.stopAct.setEnabled(True)
 2096         
 2097         if dlg.clearHistories():
 2098             self.setArgvHistory("", clearHistories=True)
 2099             self.setWdHistory("", clearHistories=True)
 2100             self.setEnvHistory("", clearHistories=True)
 2101         elif dlg.historiesModified():
 2102             argvHistory, wdHistory, envHistory = dlg.getHistories()
 2103             self.setArgvHistory("", history=argvHistory)
 2104             self.setWdHistory("", history=wdHistory)
 2105             self.setEnvHistory("", history=envHistory)
 2106     
 2107     def __doRestart(self):
 2108         """
 2109         Private slot to handle the restart action to restart the last
 2110         debugged file.
 2111         """
 2112         self.__resetUI()
 2113         doNotStart = False
 2114         
 2115         # first save any changes
 2116         if self.lastStartAction in [1, 3, 5, 7, 9]:
 2117             editor = self.viewmanager.getOpenEditor(self.lastDebuggedFile)
 2118             if (
 2119                 editor and
 2120                 not self.viewmanager.checkDirty(
 2121                     editor, Preferences.getDebugger("Autosave"))
 2122             ):
 2123                 return
 2124             forProject = False
 2125         elif self.lastStartAction in [2, 4, 6, 8, 10]:
 2126             if (
 2127                 Preferences.getDebugger("Autosave") and
 2128                 not self.project.saveAllScripts(reportSyntaxErrors=True)
 2129             ):
 2130                 doNotStart = True
 2131             self.__compileChangedProjectFiles()
 2132             forProject = True
 2133         else:
 2134             return      # should not happen
 2135                     
 2136         # get the saved stuff
 2137         venvName = self.lastUsedVenvName
 2138         wd = self.wdHistory[0]
 2139         argv = self.argvHistory[0]
 2140         fn = self.lastDebuggedFile
 2141         env = self.envHistory[0]
 2142         
 2143         # Hide all error highlights
 2144         self.viewmanager.unhighlight()
 2145         
 2146         if not doNotStart:
 2147             if forProject and self.project.getProjectType() in [
 2148                     "E6Plugin"]:
 2149                 argv = '--plugin="{0}" {1}'.format(fn, argv)
 2150                 fn = os.path.join(getConfig('ericDir'), "eric6.py")
 2151             
 2152             self.debugViewer.initCallStackViewer(forProject)
 2153             
 2154             if self.lastStartAction in [1, 2]:
 2155                 # Ask the client to send call trace info
 2156                 enableCallTrace = self.debugViewer.isCallTraceEnabled()
 2157                 self.debugViewer.clearCallTrace()
 2158                 self.debugViewer.setCallTraceToProjectMode(forProject)
 2159                 
 2160                 # Ask the client to debug the new program.
 2161                 self.debugServer.remoteLoad(
 2162                     venvName, fn, argv, wd, env,
 2163                     autoClearShell=self.autoClearShell,
 2164                     tracePython=self.tracePython,
 2165                     autoContinue=self.autoContinue,
 2166                     forProject=forProject,
 2167                     runInConsole=self.runInConsole,
 2168                     autoFork=self.forkAutomatically,
 2169                     forkChild=self.forkIntoChild,
 2170                     clientType=self.clientType,
 2171                     enableCallTrace=enableCallTrace)
 2172                 
 2173                 # Signal that we have started a debugging session
 2174                 self.debuggingStarted.emit(fn)
 2175             
 2176             elif self.lastStartAction in [3, 4]:
 2177                 # Ask the client to run the new program.
 2178                 self.debugServer.remoteRun(
 2179                     venvName, fn, argv, wd, env,
 2180                     autoClearShell=self.autoClearShell,
 2181                     forProject=forProject,
 2182                     runInConsole=self.runInConsole,
 2183                     autoFork=self.forkAutomatically,
 2184                     forkChild=self.forkIntoChild,
 2185                     clientType=self.clientType)
 2186             
 2187             elif self.lastStartAction in [5, 6]:
 2188                 # Ask the client to coverage run the new program.
 2189                 self.debugServer.remoteCoverage(
 2190                     venvName, fn, argv, wd, env,
 2191                     autoClearShell=self.autoClearShell,
 2192                     erase=self.eraseCoverage,
 2193                     forProject=forProject,
 2194                     runInConsole=self.runInConsole,
 2195                     clientType=self.clientType)
 2196             
 2197             elif self.lastStartAction in [7, 8]:
 2198                 # Ask the client to profile run the new program.
 2199                 self.debugServer.remoteProfile(
 2200                     venvName, fn, argv, wd, env,
 2201                     autoClearShell=self.autoClearShell,
 2202                     erase=self.eraseTimings,
 2203                     forProject=forProject,
 2204                     runInConsole=self.runInConsole,
 2205                     clientType=self.clientType)
 2206             
 2207             self.stopAct.setEnabled(True)
 2208         
 2209     def __stopScript(self):
 2210         """
 2211         Private slot to stop the running script.
 2212         """
 2213         self.debugServer.startClient(False)
 2214         
 2215     def __passiveDebugStarted(self, fn, exc):
 2216         """
 2217         Private slot to handle a passive debug session start.
 2218         
 2219         @param fn filename of the debugged script
 2220         @param exc flag to enable exception reporting of the IDE (boolean)
 2221         """
 2222         # Hide all error highlights
 2223         self.viewmanager.unhighlight()
 2224         
 2225         # Set filename of script being debugged
 2226         self.ui.currentProg = fn
 2227         
 2228         # Set exception reporting
 2229         self.setExceptionReporting(exc)
 2230         
 2231         # Signal that we have started a debugging session
 2232         self.debuggingStarted.emit(fn)
 2233         
 2234         # Initialize the call stack viewer
 2235         self.debugViewer.initCallStackViewer(False)
 2236         
 2237     def __continue(self):
 2238         """
 2239         Private method to handle the Continue action.
 2240         """
 2241         self.lastAction = 0
 2242         self.__enterRemote()
 2243         self.debugServer.remoteContinue()
 2244 
 2245     def __specialContinue(self):
 2246         """
 2247         Private method to handle the Special Continue action.
 2248         """
 2249         self.lastAction = 2
 2250         self.__enterRemote()
 2251         self.debugServer.remoteContinue(1)
 2252 
 2253     def __step(self):
 2254         """
 2255         Private method to handle the Step action.
 2256         """
 2257         self.lastAction = 1
 2258         self.__enterRemote()
 2259         self.debugServer.remoteStep()
 2260 
 2261     def __stepOver(self):
 2262         """
 2263         Private method to handle the Step Over action.
 2264         """
 2265         self.lastAction = 2
 2266         self.__enterRemote()
 2267         self.debugServer.remoteStepOver()
 2268 
 2269     def __stepOut(self):
 2270         """
 2271         Private method to handle the Step Out action.
 2272         """
 2273         self.lastAction = 3
 2274         self.__enterRemote()
 2275         self.debugServer.remoteStepOut()
 2276 
 2277     def __stepQuit(self):
 2278         """
 2279         Private method to handle the Step Quit action.
 2280         """
 2281         self.lastAction = 4
 2282         self.__enterRemote()
 2283         self.debugServer.remoteStepQuit()
 2284         self.__resetUI()
 2285 
 2286     def __runToCursor(self):
 2287         """
 2288         Private method to handle the Run to Cursor action.
 2289         """
 2290         self.lastAction = 0
 2291         aw = self.viewmanager.activeWindow()
 2292         line = aw.getCursorPosition()[0] + 1
 2293         self.__enterRemote()
 2294         self.debugServer.remoteBreakpoint(
 2295             aw.getFileName(), line, 1, None, 1)
 2296         self.debugServer.remoteContinue()
 2297 
 2298     def __moveInstructionPointer(self):
 2299         """
 2300         Private method to move the instruction pointer to a different line.
 2301         """
 2302         self.lastAction = 0
 2303         aw = self.viewmanager.activeWindow()
 2304         line = aw.getCursorPosition()[0] + 1
 2305         self.debugServer.remoteMoveIP(line)
 2306 
 2307     def __enterRemote(self):
 2308         """
 2309         Private method to update the user interface.
 2310 
 2311         This method is called just prior to executing some of
 2312         the program being debugged.
 2313         """
 2314         # Disable further debug commands from the user.
 2315         self.debugActGrp.setEnabled(False)
 2316         
 2317         self.viewmanager.unhighlight(True)
 2318 
 2319     def getActions(self):
 2320         """
 2321         Public method to get a list of all actions.
 2322         
 2323         @return list of all actions (list of E5Action)
 2324         """
 2325         return self.actions[:]