diff -r e9e7eca7efee -r bf71ee032bb4 src/eric7/Debugger/CallStackViewer.py --- a/src/eric7/Debugger/CallStackViewer.py Wed Jul 13 11:16:20 2022 +0200 +++ b/src/eric7/Debugger/CallStackViewer.py Wed Jul 13 14:55:47 2022 +0200 @@ -11,7 +11,12 @@ from PyQt6.QtCore import pyqtSignal, Qt from PyQt6.QtWidgets import ( - QTreeWidget, QTreeWidgetItem, QMenu, QWidget, QVBoxLayout, QLabel + QTreeWidget, + QTreeWidgetItem, + QMenu, + QWidget, + QVBoxLayout, + QLabel, ) from EricWidgets.EricApplication import ericApp @@ -21,92 +26,93 @@ class CallStackViewer(QWidget): """ Class implementing the Call Stack viewer widget. - + @signal sourceFile(str, int) emitted to show the source of a stack entry @signal frameSelected(int) emitted to signal the selection of a frame entry """ + sourceFile = pyqtSignal(str, int) frameSelected = pyqtSignal(int) - + FilenameRole = Qt.ItemDataRole.UserRole + 1 LinenoRole = Qt.ItemDataRole.UserRole + 2 - + def __init__(self, debugServer, parent=None): """ Constructor - + @param debugServer reference to the debug server object @type DebugServer @param parent reference to the parent widget @type QWidget """ super().__init__(parent) - + self.__layout = QVBoxLayout(self) self.setLayout(self.__layout) self.__debuggerLabel = QLabel(self) self.__layout.addWidget(self.__debuggerLabel) self.__callStackList = QTreeWidget(self) self.__layout.addWidget(self.__callStackList) - + self.__callStackList.setHeaderHidden(True) self.__callStackList.setAlternatingRowColors(True) self.__callStackList.setItemsExpandable(False) self.__callStackList.setRootIsDecorated(False) self.setWindowTitle(self.tr("Call Stack")) - + self.__menu = QMenu(self.__callStackList) self.__sourceAct = self.__menu.addAction( - self.tr("Show source"), self.__openSource) + self.tr("Show source"), self.__openSource + ) self.__menu.addAction(self.tr("Clear"), self.__callStackList.clear) self.__menu.addSeparator() self.__menu.addAction(self.tr("Save"), self.__saveStackTrace) self.__callStackList.setContextMenuPolicy( - Qt.ContextMenuPolicy.CustomContextMenu) - self.__callStackList.customContextMenuRequested.connect( - self.__showContextMenu) - + Qt.ContextMenuPolicy.CustomContextMenu + ) + self.__callStackList.customContextMenuRequested.connect(self.__showContextMenu) + self.__dbs = debugServer - + # file name, line number, function name, arguments self.__entryFormat = self.tr("File: {0}\nLine: {1}\n{2}{3}") # file name, line number self.__entryFormatShort = self.tr("File: {0}\nLine: {1}") - + self.__projectMode = False self.__project = None - + self.__dbs.clientStack.connect(self.__showCallStack) - self.__callStackList.itemDoubleClicked.connect( - self.__itemDoubleClicked) - + self.__callStackList.itemDoubleClicked.connect(self.__itemDoubleClicked) + def setDebugger(self, debugUI): """ Public method to set a reference to the Debug UI. - + @param debugUI reference to the DebugUI object @type DebugUI """ debugUI.clientStack.connect(self.__showCallStack) - + def setProjectMode(self, enabled): """ Public slot to set the call trace viewer to project mode. - + In project mode the call trace info is shown with project relative path names. - + @param enabled flag indicating to enable the project mode @type bool """ self.__projectMode = enabled if enabled and self.__project is None: self.__project = ericApp().getObject("Project") - + def __showContextMenu(self, coord): """ Private slot to show the context menu. - + @param coord the position of the mouse pointer @type QPoint """ @@ -114,18 +120,18 @@ itm = self.__callStackList.currentItem() self.__sourceAct.setEnabled(itm is not None) self.__menu.popup(self.__callStackList.mapToGlobal(coord)) - + def clear(self): """ Public method to clear the stack viewer data. """ self.__debuggerLabel.clear() self.__callStackList.clear() - + def __showCallStack(self, stack, debuggerId): """ Private slot to show the call stack of the program being debugged. - + @param stack list of tuples with call stack data (file name, line number, function name, formatted argument/values list) @type list of tuples of (str, str, str, str) @@ -133,36 +139,35 @@ @type str """ self.__debuggerLabel.setText(debuggerId) - + self.__callStackList.clear() for fname, fline, ffunc, fargs in stack: dfname = ( - self.__project.getRelativePath(fname) - if self.__projectMode else - fname + self.__project.getRelativePath(fname) if self.__projectMode else fname ) itm = ( # use normal format QTreeWidgetItem( self.__callStackList, - [self.__entryFormat.format(dfname, fline, ffunc, fargs)] + [self.__entryFormat.format(dfname, fline, ffunc, fargs)], ) - if ffunc and not ffunc.startswith("<") else + if ffunc and not ffunc.startswith("<") + else # use short format QTreeWidgetItem( self.__callStackList, - [self.__entryFormatShort.format(dfname, fline)] + [self.__entryFormatShort.format(dfname, fline)], ) ) itm.setData(0, self.FilenameRole, fname) itm.setData(0, self.LinenoRole, fline) - + self.__callStackList.resizeColumnToContents(0) - + def __itemDoubleClicked(self, itm): """ Private slot to handle a double click of a stack entry. - + @param itm reference to the double clicked item @type QTreeWidgetItem """ @@ -171,10 +176,10 @@ if self.__projectMode: fname = self.__project.getAbsolutePath(fname) self.sourceFile.emit(fname, fline) - + index = self.__callStackList.indexOfTopLevelItem(itm) self.frameSelected.emit(index) - + def __openSource(self): """ Private slot to show the source for the selected stack entry. @@ -182,7 +187,7 @@ itm = self.__callStackList.currentItem() if itm: self.__itemDoubleClicked(itm) - + def __saveStackTrace(self): """ Private slot to save the stack trace info to a file. @@ -194,7 +199,8 @@ "", self.tr("Text Files (*.txt);;All Files (*)"), None, - EricFileDialog.DontConfirmOverwrite) + EricFileDialog.DontConfirmOverwrite, + ) if fname: fpath = pathlib.Path(fname) if not fpath.suffix: @@ -205,15 +211,19 @@ res = EricMessageBox.yesNo( self, self.tr("Save Call Stack Info"), - self.tr("<p>The file <b>{0}</b> already exists." - " Overwrite it?</p>").format(fpath), - icon=EricMessageBox.Warning) + self.tr( + "<p>The file <b>{0}</b> already exists." + " Overwrite it?</p>" + ).format(fpath), + icon=EricMessageBox.Warning, + ) if not res: return - + try: title = self.tr("Call Stack of '{0}'").format( - self.__debuggerLabel.text()) + self.__debuggerLabel.text() + ) with fpath.open("w", encoding="utf-8") as f: f.write("{0}\n".format(title)) f.write("{0}\n\n".format(len(title) * "=")) @@ -226,7 +236,9 @@ EricMessageBox.critical( self, self.tr("Error saving Call Stack Info"), - self.tr("""<p>The call stack info could not be""" - """ written to <b>{0}</b></p>""" - """<p>Reason: {1}</p>""") - .format(fpath, str(err))) + self.tr( + """<p>The call stack info could not be""" + """ written to <b>{0}</b></p>""" + """<p>Reason: {1}</p>""" + ).format(fpath, str(err)), + )