eric6/Debugger/DebugViewer.py

changeset 7986
2971d5d19951
parent 7933
ca1b44d522b9
child 8043
0acf98cd089a
child 8143
2c730d5fd177
--- a/eric6/Debugger/DebugViewer.py	Fri Jan 15 19:46:04 2021 +0100
+++ b/eric6/Debugger/DebugViewer.py	Fri Jan 15 19:49:36 2021 +0100
@@ -8,7 +8,8 @@
 
 The views avaliable are:
 <ul>
-  <li>selector showing all connected debugger backends</li>
+  <li>selector showing all connected debugger backends with associated
+      threads</li>
   <li>variables viewer for global variables for the selected debug client</li>
   <li>variables viewer for local variables for the selected debug client</li>
   <li>call stack viewer for the selected debug client</li>
@@ -16,13 +17,13 @@
   <li>viewer for breakpoints</li>
   <li>viewer for watch expressions</li>
   <li>viewer for exceptions</li>
-  <li>viewer for threads for the selected debug client</li>
+  <li>viewer for a code disassembly for an exception<li>
 </ul>
 """
 
 import os
 
-from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt
+from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QCoreApplication
 from PyQt5.QtWidgets import (
     QWidget, QVBoxLayout, QHBoxLayout, QLineEdit, QSizePolicy, QPushButton,
     QComboBox, QLabel, QTreeWidget, QTreeWidgetItem, QHeaderView, QSplitter
@@ -52,6 +53,26 @@
     ThreadIdRole = Qt.UserRole + 1
     DebuggerStateRole = Qt.UserRole + 2
     
+    # Map debug state to icon name
+    StateIcon = {
+        "broken": "break",
+        "exception": "exceptions",
+        "running": "mediaPlaybackStart",
+        "syntax": "syntaxError22",
+    }
+    
+    # Map debug state to user message
+    StateMessage = {
+        "broken": QCoreApplication.translate(
+            "DebugViewer", "waiting at breakpoint"),
+        "exception": QCoreApplication.translate(
+            "DebugViewer", "waiting at exception"),
+        "running": QCoreApplication.translate(
+            "DebugViewer", "running"),
+        "syntax": QCoreApplication.translate(
+            "DebugViewer", "syntax error"),
+    }
+    
     def __init__(self, debugServer, parent=None):
         """
         Constructor
@@ -454,7 +475,7 @@
                 self.stackComboBox.addItem('{0}:{1}:{2}'.format(*s))
             self.stackComboBox.blockSignals(block)
     
-    def __clientLine(self, fn, line, debuggerId):
+    def __clientLine(self, fn, line, debuggerId, threadName):
         """
         Private method to handle a change to the current line.
         
@@ -464,8 +485,11 @@
         @type int
         @param debuggerId ID of the debugger backend
         @type str
+        @param threadName name of the thread signaling the event
+        @type str
         """
-        self.__setDebuggerIconAndState(debuggerId, "break", "broken")
+        self.__setDebuggerIconAndState(debuggerId, "broken")
+        self.__setThreadIconAndState(debuggerId, threadName, "broken")
         if debuggerId != self.getSelectedDebuggerId():
             self.__setCurrentDebugger(debuggerId)
     
@@ -499,7 +523,7 @@
             self.__removeDebugger(debuggerId)
     
     def __clientSyntaxError(self, message, filename, lineNo, characterNo,
-                            debuggerId):
+                            debuggerId, threadName):
         """
         Private method to handle a syntax error in the debugged program.
         
@@ -513,12 +537,14 @@
         @type int
         @param debuggerId ID of the debugger backend
         @type str
+        @param threadName name of the thread signaling the event
+        @type str
         """
-        self.__setDebuggerIconAndState(debuggerId, "syntaxError22",
-                                       "exception")
+        self.__setDebuggerIconAndState(debuggerId, "syntax")
+        self.__setThreadIconAndState(debuggerId, threadName, "syntax")
     
     def __clientException(self, exceptionType, exceptionMessage, stackTrace,
-                          debuggerId):
+                          debuggerId, threadName):
         """
         Private method to handle an exception of the debugged program.
         
@@ -530,8 +556,11 @@
         @type list of str
         @param debuggerId ID of the debugger backend
         @type str
+        @param threadName name of the thread signaling the event
+        @type str
         """
-        self.__setDebuggerIconAndState(debuggerId, "exceptions", "exception")
+        self.__setDebuggerIconAndState(debuggerId, "exception")
+        self.__setThreadIconAndState(debuggerId, threadName, "exception")
     
     def setVariablesFilter(self, globalsFilter, localsFilter):
         """
@@ -760,15 +789,13 @@
         else:
             return ""
     
-    def __setDebuggerIconAndState(self, debuggerId, iconName, state):
+    def __setDebuggerIconAndState(self, debuggerId, state):
         """
         Private method to set the icon for a specific debugger ID.
         
         @param debuggerId ID of the debugger backend (empty ID means the
             currently selected one)
         @type str
-        @param iconName name of the icon to be used
-        @type str
         @param state state of the debugger (broken, exception, running)
         @type str
         """
@@ -781,17 +808,17 @@
         if debuggerItem is None:
             debuggerItem = self.__debuggersList.currentItem()
         if debuggerItem is not None:
+            try:
+                iconName = DebugViewer.StateIcon[state]
+            except KeyError:
+                iconName = "question"
+            try:
+                stateText = DebugViewer.StateMessage[state]
+            except KeyError:
+                stateText = self.tr("unknown state ({0})").format(state)
             debuggerItem.setIcon(0, UI.PixmapCache.getIcon(iconName))
             debuggerItem.setData(0, self.DebuggerStateRole, state)
-            if state == "broken":
-                debuggerItem.setText(1, self.tr("waiting at breakpoint"))
-            elif state == "exception":
-                debuggerItem.setText(1, self.tr("waiting at exception"))
-            elif state == "running":
-                debuggerItem.setText(1, self.tr("running"))
-            else:
-                debuggerItem.setText(
-                    1, self.tr("unknown state ({0})").format(state))
+            debuggerItem.setText(1, stateText)
             
             self.__debuggersList.header().resizeSections(
                 QHeaderView.ResizeToContents)
@@ -838,20 +865,21 @@
             debuggerItem.takeChildren()
             for thread in threadList:
                 if thread.get('except', False):
-                    state = self.tr("waiting at exception")
-                    icon = "exceptions"
+                    stateText = DebugViewer.StateMessage["exception"]
+                    iconName = DebugViewer.StateIcon["exception"]
                     debugStatus = 1
                 elif thread['broken']:
-                    state = self.tr("waiting at breakpoint")
-                    icon = "break"
+                    stateText = DebugViewer.StateMessage["broken"]
+                    iconName = DebugViewer.StateIcon["broken"]
                     if debugStatus < 1:
                         debugStatus = 0
                 else:
-                    state = self.tr("running")
-                    icon = "mediaPlaybackStart"
-                itm = QTreeWidgetItem(debuggerItem, [thread['name'], state])
+                    stateText = DebugViewer.StateMessage["running"]
+                    iconName = DebugViewer.StateIcon["running"]
+                itm = QTreeWidgetItem(debuggerItem,
+                                      [thread['name'], stateText])
                 itm.setData(0, self.ThreadIdRole, thread['id'])
-                itm.setIcon(0, UI.PixmapCache.getIcon(icon))
+                itm.setIcon(0, UI.PixmapCache.getIcon(iconName))
                 if currentChild == thread['name']:
                     self.__debuggersList.setCurrentItem(itm)
                 if thread['id'] == currentID:
@@ -867,12 +895,53 @@
             self.__doDebuggersListUpdate = True
             
             if debugStatus == -1:
-                icon = "mediaPlaybackStart"
-                state = "running"
+                debuggerState = "running"
             elif debugStatus == 0:
-                icon = "break"
-                state = "broken"
+                debuggerState = "broken"
             else:
-                icon = "exceptions"
-                state = "exception"
-            self.__setDebuggerIconAndState(debuggerId, icon, state)
+                debuggerState = "exception"
+            self.__setDebuggerIconAndState(debuggerId, debuggerState)
+    
+    def __setThreadIconAndState(self, debuggerId, threadName, state):
+        """
+        Private method to set the icon for a specific thread name and
+        debugger ID.
+        
+        @param debuggerId ID of the debugger backend (empty ID means the
+            currently selected one)
+        @type str
+        @param threadName name of the thread signaling the event
+        @type str
+        @param state state of the debugger (broken, exception, running)
+        @type str
+        """
+        debuggerItem = None
+        if debuggerId:
+            foundItems = self.__debuggersList.findItems(
+                debuggerId, Qt.MatchExactly)
+            if foundItems:
+                debuggerItem = foundItems[0]
+        if debuggerItem is None:
+            debuggerItem = self.__debuggersList.currentItem()
+        if debuggerItem is not None:
+            for index in range(debuggerItem.childCount()):
+                childItem = debuggerItem.child(index)
+                if childItem.text(0) == threadName:
+                    break
+            else:
+                childItem = None
+            
+            if childItem is not None:
+                try:
+                    iconName = DebugViewer.StateIcon[state]
+                except KeyError:
+                    iconName = "question"
+                try:
+                    stateText = DebugViewer.StateMessage[state]
+                except KeyError:
+                    stateText = self.tr("unknown state ({0})").format(state)
+                childItem.setIcon(0, UI.PixmapCache.getIcon(iconName))
+                childItem.setText(1, stateText)
+            
+            self.__debuggersList.header().resizeSections(
+                QHeaderView.ResizeToContents)

eric ide

mercurial