--- a/eric6/Debugger/DebugViewer.py Wed Dec 16 20:27:57 2020 +0100 +++ b/eric6/Debugger/DebugViewer.py Thu Dec 17 13:54:47 2020 +0100 @@ -77,13 +77,17 @@ self.__debuggersLayout = QVBoxLayout(self.__debuggersWidget) self.__debuggersLayout.setContentsMargins(0, 0, 0, 0) self.__debuggersLayout.addWidget(QLabel(self.tr("Debuggers:"))) - self.__debuggersCombo = QComboBox(self) - self.__debuggersCombo.setSizePolicy( - QSizePolicy.Expanding, QSizePolicy.Fixed) - self.__debuggersLayout.addWidget(self.__debuggersCombo) + 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.setAlternatingRowColors(True) + self.__debuggersLayout.addWidget(self.__debuggersList) self.__mainSplitter.addWidget(self.__debuggersWidget) - self.__debuggersCombo.currentIndexChanged[str].connect( + self.__debuggersList.currentItemChanged.connect( self.__debuggerSelected) # add the tab widget containing various debug related views @@ -264,6 +268,8 @@ 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) @@ -342,7 +348,7 @@ self.__threadList.clear() self.__tabWidget.setCurrentWidget(self.glvWidget) self.breakpointViewer.handleResetUI() - self.__debuggersCombo.clear() + self.__debuggersList.clear() self.disassemblyViewer.clear() def initCallStackViewer(self, projectMode): @@ -424,7 +430,7 @@ @param debuggerId ID of the debugger backend @type str """ - if debuggerId == self.__debuggersCombo.currentText(): + if debuggerId == self.getSelectedDebuggerId(): block = self.stackComboBox.blockSignals(True) self.framenr = 0 self.stackComboBox.clear() @@ -449,7 +455,7 @@ """ self.__setDebuggerIconAndState(debuggerId, "break", "broken") if debuggerId != self.getSelectedDebuggerId(): - self.__debuggersCombo.setCurrentText(debuggerId) + self.__setCurrentDebugger(debuggerId) @pyqtSlot(str, int, str, bool, str) def __clientExit(self, program, status, message, quiet, debuggerId): @@ -477,8 +483,7 @@ self.currentStack = None self.stackComboBox.clear() self.__threadList.clear() - index = self.__debuggersCombo.findText(debuggerId, Qt.MatchExactly) - self.__debuggersCombo.removeItem(index) + self.__removeDebugger(debuggerId) def __clientSyntaxError(self, message, filename, lineNo, characterNo, debuggerId): @@ -618,7 +623,7 @@ """ debugStatus = -1 # i.e. running - if debuggerId == self.__debuggersCombo.currentText(): + if debuggerId == self.getSelectedDebuggerId(): citm = None self.__threadList.clear() @@ -691,13 +696,20 @@ if frameNo >= 0: self.stackComboBox.setCurrentIndex(frameNo) - def __debuggerSelected(self, debuggerId): + def __debuggerSelected(self, current, previous): """ - Private slot to handle the selection of a debugger backend ID. + Private slot to handle the selection of a debugger backend in the + debuggers list. - @param debuggerId ID of the selected debugger backend - @type str + @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: + debuggerId = current.text(0) + else: + debuggerId = "" if debuggerId: self.globalsViewer.handleResetUI() self.localsViewer.handleResetUI() @@ -718,10 +730,29 @@ @param debuggerId ID of a newly connected debugger backend @type str """ - self.__debuggersCombo.addItem(debuggerId) + itm = QTreeWidgetItem(self.__debuggersList, [debuggerId]) self.debugUI.showNotification( self.tr("<p>Debugger with ID <b>{0}</b> has been connected.") .format(debuggerId)) + + self.__debuggersList.header().resizeSections( + QHeaderView.ResizeToContents) + + if self.__debuggersList.topLevelItemCount() == 1: + # it is the only item, select it as the current one + self.__debuggersList.setCurrentItem(itm) + + def __setCurrentDebugger(self, debuggerId): + """ + Private method to set the current debugger based on the given ID. + + @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]) def getSelectedDebuggerId(self): """ @@ -730,7 +761,11 @@ @return selected debugger ID @rtype str """ - return self.__debuggersCombo.currentText() + itm = self.__debuggersList.currentItem() + if itm: + return itm.text(0) + else: + return "" def getSelectedDebuggerState(self): """ @@ -739,7 +774,11 @@ @return selected debugger's state (broken, exception, running) @rtype str """ - return self.__debuggersCombo.currentData() + itm = self.__debuggersList.currentItem() + if itm: + return itm.data(0, Qt.UserRole) + else: + return "" def __setDebuggerIconAndState(self, debuggerId, iconName, state): """ @@ -753,11 +792,41 @@ @param state state of the debugger (broken, exception, running) @type str """ + debuggerItem = None if debuggerId: - index = self.__debuggersCombo.findText(debuggerId, Qt.MatchExactly) - else: - index = self.__debuggersCombo.currentIndex() - if index >= 0: - self.__debuggersCombo.setItemIcon( - index, UI.PixmapCache.getIcon(iconName)) - self.__debuggersCombo.setItemData(index, state) + 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: + debuggerItem.setIcon(0, UI.PixmapCache.getIcon(iconName)) + debuggerItem.setData(0, Qt.UserRole, 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)) + + self.__debuggersList.header().resizeSections( + QHeaderView.ResizeToContents) + + def __removeDebugger(self, debuggerId): + """ + Private method to remove a debugger given its ID. + + @param debuggerId ID of the debugger to be removed from the list + @type str + """ + foundItems = self.__debuggersList.findItems( + debuggerId, Qt.MatchExactly) + if foundItems: + index = self.__debuggersList.indexOfTopLevelItem(foundItems[0]) + itm = self.__debuggersList.takeTopLevelItem(index) + # __IGNORE_WARNING__ + del itm