eric6/Debugger/DebugViewer.py

changeset 7920
322d1ee01510
parent 7915
e68f5c568aee
child 7923
91e843545d9a
diff -r e04b7a25e241 -r 322d1ee01510 eric6/Debugger/DebugViewer.py
--- a/eric6/Debugger/DebugViewer.py	Mon Dec 28 19:43:35 2020 +0100
+++ b/eric6/Debugger/DebugViewer.py	Tue Dec 29 20:06:50 2020 +0100
@@ -50,6 +50,7 @@
     preferencesChanged = pyqtSignal()
     
     ThreadIdRole = Qt.UserRole + 1
+    DebuggerStateRole = Qt.UserRole + 2
     
     def __init__(self, debugServer, parent=None):
         """
@@ -78,13 +79,14 @@
         self.__debuggersWidget = QWidget()
         self.__debuggersLayout = QVBoxLayout(self.__debuggersWidget)
         self.__debuggersLayout.setContentsMargins(0, 0, 0, 0)
-        self.__debuggersLayout.addWidget(QLabel(self.tr("Debuggers:")))
+        self.__debuggersLayout.addWidget(
+            QLabel(self.tr("Debuggers and Threads:")))
         self.__debuggersList = QTreeWidget()
         self.__debuggersList.setHeaderLabels(
             [self.tr("ID"), self.tr("State"), ""])
         self.__debuggersList.header().setStretchLastSection(True)
         self.__debuggersList.setSortingEnabled(True)
-        self.__debuggersList.setRootIsDecorated(False)
+        self.__debuggersList.setRootIsDecorated(True)
         self.__debuggersList.setAlternatingRowColors(True)
         self.__debuggersLayout.addWidget(self.__debuggersList)
         self.__mainSplitter.addWidget(self.__debuggersWidget)
@@ -271,25 +273,9 @@
         
         self.__tabWidget.setCurrentWidget(self.glvWidget)
         
-        # add the threads viewer
-        self.__threadWidget = QWidget()
-        self.__threadWidgetLayout = QVBoxLayout(self.__threadWidget)
-        self.__threadWidgetLayout.setContentsMargins(0, 0, 0, 0)
-        self.__threadWidgetLayout.addWidget(QLabel(self.tr("Threads:")))
-        self.__threadList = QTreeWidget()
-        self.__threadList.setHeaderLabels(
-            [self.tr("Name"), self.tr("State"), ""])
-        self.__threadList.setSortingEnabled(True)
-        self.__threadList.setRootIsDecorated(False)
-        self.__threadList.setAlternatingRowColors(True)
-        self.__threadWidgetLayout.addWidget(self.__threadList)
-        self.__mainSplitter.addWidget(self.__threadWidget)
+        self.__doDebuggersListUpdate = True
         
-        self.__doThreadListUpdate = True
-        
-        self.__threadList.currentItemChanged.connect(self.__threadSelected)
-        
-        self.__mainSplitter.setSizes([50, 700, 50])
+        self.__mainSplitter.setSizes([100, 700])
         
         self.currentStack = None
         self.framenr = 0
@@ -297,11 +283,11 @@
         self.__autoViewSource = Preferences.getDebugger("AutoViewSourceCode")
         self.sourceButton.setVisible(not self.__autoViewSource)
         
-        # connect somer debug server signals
+        # connect some debug server signals
         self.debugServer.clientStack.connect(
             self.handleClientStack)
         self.debugServer.clientThreadList.connect(
-            self.showThreadList)
+            self.__addThreadList)
         self.debugServer.clientDebuggerId.connect(
             self.__clientDebuggerId)
         self.debugServer.passiveDebugStarted.connect(
@@ -358,7 +344,6 @@
         self.sourceButton.setEnabled(False)
         self.currentStack = None
         self.stackComboBox.clear()
-        self.__threadList.clear()
         self.__tabWidget.setCurrentWidget(self.glvWidget)
         self.breakpointViewer.handleResetUI()
         self.__debuggersList.clear()
@@ -504,7 +489,6 @@
                 self.sourceButton.setEnabled(False)
                 self.currentStack = None
                 self.stackComboBox.clear()
-                self.__threadList.clear()
             
             self.__removeDebugger(debuggerId)
     
@@ -635,83 +619,6 @@
         @type QWidget
         """
         self.__tabWidget.setCurrentWidget(widget)
-        
-    def showThreadList(self, currentID, threadList, debuggerId):
-        """
-        Public method to show the thread list.
-        
-        @param currentID id of the current thread
-        @type int
-        @param threadList list of dictionaries containing the thread data
-        @type list of dict
-        @param debuggerId ID of the debugger backend
-        @type str
-        """
-        debugStatus = -1    # i.e. running
-        
-        if debuggerId == self.getSelectedDebuggerId():
-            citm = None
-            
-            self.__threadList.clear()
-            for thread in threadList:
-                if thread.get('except', False):
-                    state = self.tr("waiting at exception")
-                    icon = "exceptions"
-                    debugStatus = 1
-                elif thread['broken']:
-                    state = self.tr("waiting at breakpoint")
-                    icon = "break"
-                    if debugStatus < 1:
-                        debugStatus = 0
-                else:
-                    state = self.tr("running")
-                    icon = "mediaPlaybackStart"
-                itm = QTreeWidgetItem(self.__threadList,
-                                      [thread['name'], state])
-                itm.setData(0, self.ThreadIdRole, thread['id'])
-                itm.setIcon(0, UI.PixmapCache.getIcon(icon))
-                if thread['id'] == currentID:
-                    citm = itm
-            
-            self.__threadList.header().resizeSections(
-                QHeaderView.ResizeToContents)
-            self.__threadList.header().setStretchLastSection(True)
-            
-            if citm:
-                self.__doThreadListUpdate = False
-                self.__threadList.setCurrentItem(citm)
-                self.__doThreadListUpdate = True
-        else:
-            for thread in threadList:
-                if thread.get('except', False):
-                    debugStatus = 1
-                elif thread['broken']:
-                    if debugStatus < 1:
-                        debugStatus = 0
-        
-        if debugStatus == -1:
-            icon = "mediaPlaybackStart"
-            state = "running"
-        elif debugStatus == 0:
-            icon = "break"
-            state = "broken"
-        else:
-            icon = "exceptions"
-            state = "exception"
-        self.__setDebuggerIconAndState(debuggerId, icon, state)
-    
-    def __threadSelected(self, current, previous):
-        """
-        Private slot to handle the selection of a thread in the thread list.
-        
-        @param current reference to the new current item
-        @type QTreeWidgetItem
-        @param previous reference to the previous current item
-        @type QTreeWidgetItem
-        """
-        if current is not None and self.__doThreadListUpdate:
-            tid = current.data(0, self.ThreadIdRole)
-            self.debugServer.remoteSetThread(self.getSelectedDebuggerId(), tid)
     
     def __callStackFrameSelected(self, frameNo):
         """
@@ -734,22 +641,25 @@
         @param previous reference to the previous current item
         @type QTreeWidgetItem
         """
-        if current is not None:
-            debuggerId = current.text(0)
-        else:
-            debuggerId = ""
-        if debuggerId:
-            self.globalsViewer.handleResetUI()
-            self.localsViewer.handleResetUI()
-            self.currentStack = None
-            self.stackComboBox.clear()
-            self.__threadList.clear()
-            self.callStackViewer.clear()
-            
-            self.debugUI.getDebuggerData(debuggerId)
-            self.debugUI.setDebugActionsEnabled(
-                self.getSelectedDebuggerState() != "running")
-            self.__showSource()
+        if current is not None and self.__doDebuggersListUpdate:
+            if current.parent() is None:
+                # it is a debugger item
+                debuggerId = current.text(0)
+                self.globalsViewer.handleResetUI()
+                self.localsViewer.handleResetUI()
+                self.currentStack = None
+                self.stackComboBox.clear()
+                self.callStackViewer.clear()
+                
+                self.debugUI.getDebuggerData(debuggerId)
+                self.debugUI.setDebugActionsEnabled(
+                    self.getSelectedDebuggerState() != "running")
+                self.__showSource()
+            else:
+                # it is a thread item
+                tid = current.data(0, self.ThreadIdRole)
+                self.debugServer.remoteSetThread(
+                    self.getSelectedDebuggerId(), tid)
     
     def __clientDebuggerId(self, debuggerId):
         """
@@ -779,10 +689,24 @@
         @param debuggerId ID of the debugger to set as current debugger
         @type str
         """
-        foundItems = self.__debuggersList.findItems(debuggerId,
-                                                    Qt.MatchExactly)
-        if foundItems:
-            self.__debuggersList.setCurrentItem(foundItems[0])
+        debuggerItems = self.__debuggersList.findItems(
+            debuggerId, Qt.MatchExactly)
+        if debuggerItems:
+            debuggerItem = debuggerItems[0]
+            currentItem = self.__debuggersList.currentItem()
+            if currentItem is debuggerItem:
+                # nothing to do
+                return
+            
+            currentParent = currentItem.parent()
+            if currentParent is None:
+                # current is a debugger item
+                self.__debuggersList.setCurrentItem(debuggerItem)
+            elif currentParent is debuggerItem:
+                # nothing to do
+                return
+            else:
+                self.__debuggersList.setCurrentItem(debuggerItem)
     
     def isOnlyDebugger(self):
         """
@@ -802,7 +726,12 @@
         """
         itm = self.__debuggersList.currentItem()
         if itm:
-            return itm.text(0)
+            if itm.parent() is None:
+                # it is a debugger item
+                return itm.text(0)
+            else:
+                # it is a thread item
+                return itm.parent().text(0)
         else:
             return ""
     
@@ -815,7 +744,12 @@
         """
         itm = self.__debuggersList.currentItem()
         if itm:
-            return itm.data(0, Qt.UserRole)
+            if itm.parent() is None:
+                # it is a debugger item
+                return itm.data(0, self.DebuggerStateRole)
+            else:
+                # it is a thread item
+                return itm.parent().data(0, self.DebuggerStateRole)
         else:
             return ""
     
@@ -841,7 +775,7 @@
             debuggerItem = self.__debuggersList.currentItem()
         if debuggerItem is not None:
             debuggerItem.setIcon(0, UI.PixmapCache.getIcon(iconName))
-            debuggerItem.setData(0, Qt.UserRole, state)
+            debuggerItem.setData(0, self.DebuggerStateRole, state)
             if state == "broken":
                 debuggerItem.setText(1, self.tr("waiting at breakpoint"))
             elif state == "exception":
@@ -869,3 +803,69 @@
             itm = self.__debuggersList.takeTopLevelItem(index)
             # __IGNORE_WARNING__
             del itm
+    
+    def __addThreadList(self, currentID, threadList, debuggerId):
+        """
+        Private method to add the list of threads to a debugger entry.
+        
+        @param currentID id of the current thread
+        @type int
+        @param threadList list of dictionaries containing the thread data
+        @type list of dict
+        @param debuggerId ID of the debugger backend
+        @type str
+        """
+        debugStatus = -1    # i.e. running
+        
+        debuggerItems = self.__debuggersList.findItems(
+            debuggerId, Qt.MatchExactly)
+        if debuggerItems:
+            debuggerItem = debuggerItems[0]
+            
+            currentItem = self.__debuggersList.currentItem()
+            if currentItem.parent() is debuggerItem:
+                currentChild = currentItem.text(0)
+            else:
+                currentChild = ""
+            self.__doDebuggersListUpdate = False
+            debuggerItem.takeChildren()
+            for thread in threadList:
+                if thread.get('except', False):
+                    state = self.tr("waiting at exception")
+                    icon = "exceptions"
+                    debugStatus = 1
+                elif thread['broken']:
+                    state = self.tr("waiting at breakpoint")
+                    icon = "break"
+                    if debugStatus < 1:
+                        debugStatus = 0
+                else:
+                    state = self.tr("running")
+                    icon = "mediaPlaybackStart"
+                itm = QTreeWidgetItem(debuggerItem, [thread['name'], state])
+                itm.setData(0, self.ThreadIdRole, thread['id'])
+                itm.setIcon(0, UI.PixmapCache.getIcon(icon))
+                if currentChild == thread['name']:
+                    self.__debuggersList.setCurrentItem(itm)
+                if thread['id'] == currentID:
+                    font = debuggerItem.font(0)
+                    font.setItalic(True)
+                    itm.setFont(0, font)
+            
+            debuggerItem.setExpanded(debuggerItem.childCount() > 0)
+            
+            self.__debuggersList.header().resizeSections(
+                QHeaderView.ResizeToContents)
+            self.__debuggersList.header().setStretchLastSection(True)
+            self.__doDebuggersListUpdate = True
+            
+            if debugStatus == -1:
+                icon = "mediaPlaybackStart"
+                state = "running"
+            elif debugStatus == 0:
+                icon = "break"
+                state = "broken"
+            else:
+                icon = "exceptions"
+                state = "exception"
+            self.__setDebuggerIconAndState(debuggerId, icon, state)

eric ide

mercurial