src/eric7/Debugger/DebugViewer.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9363
789d739a683a
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
23 23
24 import os 24 import os
25 25
26 from PyQt6.QtCore import pyqtSignal, pyqtSlot, Qt, QCoreApplication 26 from PyQt6.QtCore import pyqtSignal, pyqtSlot, Qt, QCoreApplication
27 from PyQt6.QtWidgets import ( 27 from PyQt6.QtWidgets import (
28 QWidget, QVBoxLayout, QHBoxLayout, QLineEdit, QSizePolicy, QPushButton, 28 QWidget,
29 QComboBox, QLabel, QTreeWidget, QTreeWidgetItem, QHeaderView, QSplitter 29 QVBoxLayout,
30 QHBoxLayout,
31 QLineEdit,
32 QSizePolicy,
33 QPushButton,
34 QComboBox,
35 QLabel,
36 QTreeWidget,
37 QTreeWidgetItem,
38 QHeaderView,
39 QSplitter,
30 ) 40 )
31 41
32 import UI.PixmapCache 42 import UI.PixmapCache
33 import Preferences 43 import Preferences
34 44
36 46
37 47
38 class DebugViewer(QWidget): 48 class DebugViewer(QWidget):
39 """ 49 """
40 Class implementing a widget containing various debug related views. 50 Class implementing a widget containing various debug related views.
41 51
42 The individual tabs contain the interpreter shell (optional), 52 The individual tabs contain the interpreter shell (optional),
43 the filesystem browser (optional), the two variables viewers 53 the filesystem browser (optional), the two variables viewers
44 (global and local), a breakpoint viewer, a watch expression viewer and 54 (global and local), a breakpoint viewer, a watch expression viewer and
45 the exception logger. Additionally a list of all threads is shown. 55 the exception logger. Additionally a list of all threads is shown.
46 56
47 @signal sourceFile(string, int) emitted to open a source file at a line 57 @signal sourceFile(string, int) emitted to open a source file at a line
48 @signal preferencesChanged() emitted to react on changed preferences 58 @signal preferencesChanged() emitted to react on changed preferences
49 """ 59 """
60
50 sourceFile = pyqtSignal(str, int) 61 sourceFile = pyqtSignal(str, int)
51 preferencesChanged = pyqtSignal() 62 preferencesChanged = pyqtSignal()
52 63
53 ThreadIdRole = Qt.ItemDataRole.UserRole + 1 64 ThreadIdRole = Qt.ItemDataRole.UserRole + 1
54 DebuggerStateRole = Qt.ItemDataRole.UserRole + 2 65 DebuggerStateRole = Qt.ItemDataRole.UserRole + 2
55 66
56 # Map debug state to icon name 67 # Map debug state to icon name
57 StateIcon = { 68 StateIcon = {
58 "broken": "break", 69 "broken": "break",
59 "exception": "exceptions", 70 "exception": "exceptions",
60 "running": "mediaPlaybackStart", 71 "running": "mediaPlaybackStart",
61 "syntax": "syntaxError22", 72 "syntax": "syntaxError22",
62 } 73 }
63 74
64 # Map debug state to user message 75 # Map debug state to user message
65 StateMessage = { 76 StateMessage = {
66 "broken": QCoreApplication.translate( 77 "broken": QCoreApplication.translate("DebugViewer", "waiting at breakpoint"),
67 "DebugViewer", "waiting at breakpoint"), 78 "exception": QCoreApplication.translate("DebugViewer", "waiting at exception"),
68 "exception": QCoreApplication.translate( 79 "running": QCoreApplication.translate("DebugViewer", "running"),
69 "DebugViewer", "waiting at exception"), 80 "syntax": QCoreApplication.translate("DebugViewer", "syntax error"),
70 "running": QCoreApplication.translate(
71 "DebugViewer", "running"),
72 "syntax": QCoreApplication.translate(
73 "DebugViewer", "syntax error"),
74 } 81 }
75 82
76 def __init__(self, debugServer, parent=None): 83 def __init__(self, debugServer, parent=None):
77 """ 84 """
78 Constructor 85 Constructor
79 86
80 @param debugServer reference to the debug server object 87 @param debugServer reference to the debug server object
81 @type DebugServer 88 @type DebugServer
82 @param parent parent widget 89 @param parent parent widget
83 @type QWidget 90 @type QWidget
84 """ 91 """
85 super().__init__(parent) 92 super().__init__(parent)
86 93
87 self.debugServer = debugServer 94 self.debugServer = debugServer
88 self.debugUI = None 95 self.debugUI = None
89 96
90 self.setWindowIcon(UI.PixmapCache.getIcon("eric")) 97 self.setWindowIcon(UI.PixmapCache.getIcon("eric"))
91 98
92 self.__mainLayout = QVBoxLayout() 99 self.__mainLayout = QVBoxLayout()
93 self.__mainLayout.setContentsMargins(0, 3, 0, 0) 100 self.__mainLayout.setContentsMargins(0, 3, 0, 0)
94 self.setLayout(self.__mainLayout) 101 self.setLayout(self.__mainLayout)
95 102
96 self.__mainSplitter = QSplitter(Qt.Orientation.Vertical, self) 103 self.__mainSplitter = QSplitter(Qt.Orientation.Vertical, self)
97 self.__mainLayout.addWidget(self.__mainSplitter) 104 self.__mainLayout.addWidget(self.__mainSplitter)
98 105
99 # add the viewer showing the connected debug backends 106 # add the viewer showing the connected debug backends
100 self.__debuggersWidget = QWidget() 107 self.__debuggersWidget = QWidget()
101 self.__debuggersLayout = QVBoxLayout(self.__debuggersWidget) 108 self.__debuggersLayout = QVBoxLayout(self.__debuggersWidget)
102 self.__debuggersLayout.setContentsMargins(0, 0, 0, 0) 109 self.__debuggersLayout.setContentsMargins(0, 0, 0, 0)
103 self.__debuggersLayout.addWidget( 110 self.__debuggersLayout.addWidget(QLabel(self.tr("Debuggers and Threads:")))
104 QLabel(self.tr("Debuggers and Threads:")))
105 self.__debuggersList = QTreeWidget() 111 self.__debuggersList = QTreeWidget()
106 self.__debuggersList.setHeaderLabels( 112 self.__debuggersList.setHeaderLabels([self.tr("ID"), self.tr("State"), ""])
107 [self.tr("ID"), self.tr("State"), ""])
108 self.__debuggersList.header().setStretchLastSection(True) 113 self.__debuggersList.header().setStretchLastSection(True)
109 self.__debuggersList.setSortingEnabled(True) 114 self.__debuggersList.setSortingEnabled(True)
110 self.__debuggersList.setRootIsDecorated(True) 115 self.__debuggersList.setRootIsDecorated(True)
111 self.__debuggersList.setAlternatingRowColors(True) 116 self.__debuggersList.setAlternatingRowColors(True)
112 self.__debuggersLayout.addWidget(self.__debuggersList) 117 self.__debuggersLayout.addWidget(self.__debuggersList)
113 self.__mainSplitter.addWidget(self.__debuggersWidget) 118 self.__mainSplitter.addWidget(self.__debuggersWidget)
114 119
115 self.__debuggersList.currentItemChanged.connect( 120 self.__debuggersList.currentItemChanged.connect(self.__debuggerSelected)
116 self.__debuggerSelected) 121
117
118 # add the tab widget containing various debug related views 122 # add the tab widget containing various debug related views
119 self.__tabWidget = EricTabWidget() 123 self.__tabWidget = EricTabWidget()
120 self.__mainSplitter.addWidget(self.__tabWidget) 124 self.__mainSplitter.addWidget(self.__tabWidget)
121 125
122 from .VariablesViewer import VariablesViewer 126 from .VariablesViewer import VariablesViewer
127
123 # add the global variables viewer 128 # add the global variables viewer
124 self.glvWidget = QWidget() 129 self.glvWidget = QWidget()
125 self.glvWidgetVLayout = QVBoxLayout(self.glvWidget) 130 self.glvWidgetVLayout = QVBoxLayout(self.glvWidget)
126 self.glvWidgetVLayout.setContentsMargins(0, 0, 0, 0) 131 self.glvWidgetVLayout.setContentsMargins(0, 0, 0, 0)
127 self.glvWidgetVLayout.setSpacing(3) 132 self.glvWidgetVLayout.setSpacing(3)
128 self.glvWidget.setLayout(self.glvWidgetVLayout) 133 self.glvWidget.setLayout(self.glvWidgetVLayout)
129 134
130 self.globalsViewer = VariablesViewer(self, True, self.glvWidget) 135 self.globalsViewer = VariablesViewer(self, True, self.glvWidget)
131 self.glvWidgetVLayout.addWidget(self.globalsViewer) 136 self.glvWidgetVLayout.addWidget(self.globalsViewer)
132 137
133 self.glvWidgetHLayout = QHBoxLayout() 138 self.glvWidgetHLayout = QHBoxLayout()
134 self.glvWidgetHLayout.setContentsMargins(3, 3, 3, 3) 139 self.glvWidgetHLayout.setContentsMargins(3, 3, 3, 3)
135 140
136 self.globalsFilterEdit = QLineEdit(self.glvWidget) 141 self.globalsFilterEdit = QLineEdit(self.glvWidget)
137 self.globalsFilterEdit.setSizePolicy( 142 self.globalsFilterEdit.setSizePolicy(
138 QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) 143 QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed
144 )
139 self.glvWidgetHLayout.addWidget(self.globalsFilterEdit) 145 self.glvWidgetHLayout.addWidget(self.globalsFilterEdit)
140 self.globalsFilterEdit.setToolTip( 146 self.globalsFilterEdit.setToolTip(
141 self.tr("Enter regular expression patterns separated by ';'" 147 self.tr(
142 " to define variable filters. ")) 148 "Enter regular expression patterns separated by ';'"
149 " to define variable filters. "
150 )
151 )
143 self.globalsFilterEdit.setWhatsThis( 152 self.globalsFilterEdit.setWhatsThis(
144 self.tr("Enter regular expression patterns separated by ';'" 153 self.tr(
145 " to define variable filters. All variables and" 154 "Enter regular expression patterns separated by ';'"
146 " class attributes matched by one of the expressions" 155 " to define variable filters. All variables and"
147 " are not shown in the list above.")) 156 " class attributes matched by one of the expressions"
148 157 " are not shown in the list above."
149 self.setGlobalsFilterButton = QPushButton( 158 )
150 self.tr('Set'), self.glvWidget) 159 )
160
161 self.setGlobalsFilterButton = QPushButton(self.tr("Set"), self.glvWidget)
151 self.glvWidgetHLayout.addWidget(self.setGlobalsFilterButton) 162 self.glvWidgetHLayout.addWidget(self.setGlobalsFilterButton)
152 self.glvWidgetVLayout.addLayout(self.glvWidgetHLayout) 163 self.glvWidgetVLayout.addLayout(self.glvWidgetHLayout)
153 164
154 index = self.__tabWidget.addTab( 165 index = self.__tabWidget.addTab(
155 self.glvWidget, 166 self.glvWidget, UI.PixmapCache.getIcon("globalVariables"), ""
156 UI.PixmapCache.getIcon("globalVariables"), '') 167 )
157 self.__tabWidget.setTabToolTip( 168 self.__tabWidget.setTabToolTip(
158 index, 169 index, self.tr("Shows the list of global variables and their values.")
159 self.tr("Shows the list of global variables and their values.")) 170 )
160 171
161 self.setGlobalsFilterButton.clicked.connect( 172 self.setGlobalsFilterButton.clicked.connect(self.setGlobalsFilter)
162 self.setGlobalsFilter)
163 self.globalsFilterEdit.returnPressed.connect(self.setGlobalsFilter) 173 self.globalsFilterEdit.returnPressed.connect(self.setGlobalsFilter)
164 174
165 # add the local variables viewer 175 # add the local variables viewer
166 self.lvWidget = QWidget() 176 self.lvWidget = QWidget()
167 self.lvWidgetVLayout = QVBoxLayout(self.lvWidget) 177 self.lvWidgetVLayout = QVBoxLayout(self.lvWidget)
168 self.lvWidgetVLayout.setContentsMargins(0, 0, 0, 0) 178 self.lvWidgetVLayout.setContentsMargins(0, 0, 0, 0)
169 self.lvWidgetVLayout.setSpacing(3) 179 self.lvWidgetVLayout.setSpacing(3)
170 self.lvWidget.setLayout(self.lvWidgetVLayout) 180 self.lvWidget.setLayout(self.lvWidgetVLayout)
171 181
172 self.lvWidgetHLayout1 = QHBoxLayout() 182 self.lvWidgetHLayout1 = QHBoxLayout()
173 self.lvWidgetHLayout1.setContentsMargins(3, 3, 3, 3) 183 self.lvWidgetHLayout1.setContentsMargins(3, 3, 3, 3)
174 184
175 self.stackComboBox = QComboBox(self.lvWidget) 185 self.stackComboBox = QComboBox(self.lvWidget)
176 self.stackComboBox.setSizePolicy( 186 self.stackComboBox.setSizePolicy(
177 QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) 187 QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed
188 )
178 self.lvWidgetHLayout1.addWidget(self.stackComboBox) 189 self.lvWidgetHLayout1.addWidget(self.stackComboBox)
179 190
180 self.sourceButton = QPushButton(self.tr('Source'), self.lvWidget) 191 self.sourceButton = QPushButton(self.tr("Source"), self.lvWidget)
181 self.lvWidgetHLayout1.addWidget(self.sourceButton) 192 self.lvWidgetHLayout1.addWidget(self.sourceButton)
182 self.sourceButton.setEnabled(False) 193 self.sourceButton.setEnabled(False)
183 self.lvWidgetVLayout.addLayout(self.lvWidgetHLayout1) 194 self.lvWidgetVLayout.addLayout(self.lvWidgetHLayout1)
184 195
185 self.localsViewer = VariablesViewer(self, False, self.lvWidget) 196 self.localsViewer = VariablesViewer(self, False, self.lvWidget)
186 self.lvWidgetVLayout.addWidget(self.localsViewer) 197 self.lvWidgetVLayout.addWidget(self.localsViewer)
187 198
188 self.lvWidgetHLayout2 = QHBoxLayout() 199 self.lvWidgetHLayout2 = QHBoxLayout()
189 self.lvWidgetHLayout2.setContentsMargins(3, 3, 3, 3) 200 self.lvWidgetHLayout2.setContentsMargins(3, 3, 3, 3)
190 201
191 self.localsFilterEdit = QLineEdit(self.lvWidget) 202 self.localsFilterEdit = QLineEdit(self.lvWidget)
192 self.localsFilterEdit.setSizePolicy( 203 self.localsFilterEdit.setSizePolicy(
193 QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) 204 QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed
205 )
194 self.lvWidgetHLayout2.addWidget(self.localsFilterEdit) 206 self.lvWidgetHLayout2.addWidget(self.localsFilterEdit)
195 self.localsFilterEdit.setToolTip( 207 self.localsFilterEdit.setToolTip(
196 self.tr( 208 self.tr(
197 "Enter regular expression patterns separated by ';' to define " 209 "Enter regular expression patterns separated by ';' to define "
198 "variable filters. ")) 210 "variable filters. "
211 )
212 )
199 self.localsFilterEdit.setWhatsThis( 213 self.localsFilterEdit.setWhatsThis(
200 self.tr( 214 self.tr(
201 "Enter regular expression patterns separated by ';' to define " 215 "Enter regular expression patterns separated by ';' to define "
202 "variable filters. All variables and class attributes matched" 216 "variable filters. All variables and class attributes matched"
203 " by one of the expressions are not shown in the list above.")) 217 " by one of the expressions are not shown in the list above."
204 218 )
205 self.setLocalsFilterButton = QPushButton( 219 )
206 self.tr('Set'), self.lvWidget) 220
221 self.setLocalsFilterButton = QPushButton(self.tr("Set"), self.lvWidget)
207 self.lvWidgetHLayout2.addWidget(self.setLocalsFilterButton) 222 self.lvWidgetHLayout2.addWidget(self.setLocalsFilterButton)
208 self.lvWidgetVLayout.addLayout(self.lvWidgetHLayout2) 223 self.lvWidgetVLayout.addLayout(self.lvWidgetHLayout2)
209 224
210 index = self.__tabWidget.addTab( 225 index = self.__tabWidget.addTab(
211 self.lvWidget, 226 self.lvWidget, UI.PixmapCache.getIcon("localVariables"), ""
212 UI.PixmapCache.getIcon("localVariables"), '') 227 )
213 self.__tabWidget.setTabToolTip( 228 self.__tabWidget.setTabToolTip(
214 index, 229 index, self.tr("Shows the list of local variables and their values.")
215 self.tr("Shows the list of local variables and their values.")) 230 )
216 231
217 self.sourceButton.clicked.connect(self.__showSource) 232 self.sourceButton.clicked.connect(self.__showSource)
218 self.stackComboBox.currentIndexChanged[int].connect( 233 self.stackComboBox.currentIndexChanged[int].connect(self.__frameSelected)
219 self.__frameSelected)
220 self.setLocalsFilterButton.clicked.connect(self.setLocalsFilter) 234 self.setLocalsFilterButton.clicked.connect(self.setLocalsFilter)
221 self.localsFilterEdit.returnPressed.connect(self.setLocalsFilter) 235 self.localsFilterEdit.returnPressed.connect(self.setLocalsFilter)
222 236
223 self.preferencesChanged.connect(self.handlePreferencesChanged) 237 self.preferencesChanged.connect(self.handlePreferencesChanged)
224 self.preferencesChanged.connect(self.globalsViewer.preferencesChanged) 238 self.preferencesChanged.connect(self.globalsViewer.preferencesChanged)
225 self.preferencesChanged.connect(self.localsViewer.preferencesChanged) 239 self.preferencesChanged.connect(self.localsViewer.preferencesChanged)
226 240
227 from .CallStackViewer import CallStackViewer 241 from .CallStackViewer import CallStackViewer
242
228 # add the call stack viewer 243 # add the call stack viewer
229 self.callStackViewer = CallStackViewer(self.debugServer) 244 self.callStackViewer = CallStackViewer(self.debugServer)
230 index = self.__tabWidget.addTab( 245 index = self.__tabWidget.addTab(
231 self.callStackViewer, 246 self.callStackViewer, UI.PixmapCache.getIcon("callStack"), ""
232 UI.PixmapCache.getIcon("callStack"), "") 247 )
233 self.__tabWidget.setTabToolTip( 248 self.__tabWidget.setTabToolTip(index, self.tr("Shows the current call stack."))
234 index,
235 self.tr("Shows the current call stack."))
236 self.callStackViewer.sourceFile.connect(self.sourceFile) 249 self.callStackViewer.sourceFile.connect(self.sourceFile)
237 self.callStackViewer.frameSelected.connect( 250 self.callStackViewer.frameSelected.connect(self.__callStackFrameSelected)
238 self.__callStackFrameSelected) 251
239
240 from .CallTraceViewer import CallTraceViewer 252 from .CallTraceViewer import CallTraceViewer
253
241 # add the call trace viewer 254 # add the call trace viewer
242 self.callTraceViewer = CallTraceViewer(self.debugServer, self) 255 self.callTraceViewer = CallTraceViewer(self.debugServer, self)
243 index = self.__tabWidget.addTab( 256 index = self.__tabWidget.addTab(
244 self.callTraceViewer, 257 self.callTraceViewer, UI.PixmapCache.getIcon("callTrace"), ""
245 UI.PixmapCache.getIcon("callTrace"), "") 258 )
246 self.__tabWidget.setTabToolTip( 259 self.__tabWidget.setTabToolTip(
247 index, 260 index, self.tr("Shows a trace of the program flow.")
248 self.tr("Shows a trace of the program flow.")) 261 )
249 self.callTraceViewer.sourceFile.connect(self.sourceFile) 262 self.callTraceViewer.sourceFile.connect(self.sourceFile)
250 263
251 from .BreakPointViewer import BreakPointViewer 264 from .BreakPointViewer import BreakPointViewer
265
252 # add the breakpoint viewer 266 # add the breakpoint viewer
253 self.breakpointViewer = BreakPointViewer() 267 self.breakpointViewer = BreakPointViewer()
254 self.breakpointViewer.setModel(self.debugServer.getBreakPointModel()) 268 self.breakpointViewer.setModel(self.debugServer.getBreakPointModel())
255 index = self.__tabWidget.addTab( 269 index = self.__tabWidget.addTab(
256 self.breakpointViewer, 270 self.breakpointViewer, UI.PixmapCache.getIcon("breakpoints"), ""
257 UI.PixmapCache.getIcon("breakpoints"), '') 271 )
258 self.__tabWidget.setTabToolTip( 272 self.__tabWidget.setTabToolTip(
259 index, 273 index, self.tr("Shows a list of defined breakpoints.")
260 self.tr("Shows a list of defined breakpoints.")) 274 )
261 self.breakpointViewer.sourceFile.connect(self.sourceFile) 275 self.breakpointViewer.sourceFile.connect(self.sourceFile)
262 276
263 from .WatchPointViewer import WatchPointViewer 277 from .WatchPointViewer import WatchPointViewer
278
264 # add the watch expression viewer 279 # add the watch expression viewer
265 self.watchpointViewer = WatchPointViewer() 280 self.watchpointViewer = WatchPointViewer()
266 self.watchpointViewer.setModel(self.debugServer.getWatchPointModel()) 281 self.watchpointViewer.setModel(self.debugServer.getWatchPointModel())
267 index = self.__tabWidget.addTab( 282 index = self.__tabWidget.addTab(
268 self.watchpointViewer, 283 self.watchpointViewer, UI.PixmapCache.getIcon("watchpoints"), ""
269 UI.PixmapCache.getIcon("watchpoints"), '') 284 )
270 self.__tabWidget.setTabToolTip( 285 self.__tabWidget.setTabToolTip(
271 index, 286 index, self.tr("Shows a list of defined watchpoints.")
272 self.tr("Shows a list of defined watchpoints.")) 287 )
273 288
274 from .ExceptionLogger import ExceptionLogger 289 from .ExceptionLogger import ExceptionLogger
290
275 # add the exception logger 291 # add the exception logger
276 self.exceptionLogger = ExceptionLogger() 292 self.exceptionLogger = ExceptionLogger()
277 index = self.__tabWidget.addTab( 293 index = self.__tabWidget.addTab(
278 self.exceptionLogger, 294 self.exceptionLogger, UI.PixmapCache.getIcon("exceptions"), ""
279 UI.PixmapCache.getIcon("exceptions"), '') 295 )
280 self.__tabWidget.setTabToolTip( 296 self.__tabWidget.setTabToolTip(
281 index, 297 index, self.tr("Shows a list of raised exceptions.")
282 self.tr("Shows a list of raised exceptions.")) 298 )
283 299
284 from UI.PythonDisViewer import PythonDisViewer, PythonDisViewerModes 300 from UI.PythonDisViewer import PythonDisViewer, PythonDisViewerModes
301
285 # add the Python disassembly viewer 302 # add the Python disassembly viewer
286 self.disassemblyViewer = PythonDisViewer( 303 self.disassemblyViewer = PythonDisViewer(
287 None, mode=PythonDisViewerModes.TRACEBACK) 304 None, mode=PythonDisViewerModes.TRACEBACK
305 )
288 index = self.__tabWidget.addTab( 306 index = self.__tabWidget.addTab(
289 self.disassemblyViewer, 307 self.disassemblyViewer, UI.PixmapCache.getIcon("disassembly"), ""
290 UI.PixmapCache.getIcon("disassembly"), '') 308 )
291 self.__tabWidget.setTabToolTip( 309 self.__tabWidget.setTabToolTip(
292 index, 310 index, self.tr("Shows a code disassembly in case of an exception.")
293 self.tr("Shows a code disassembly in case of an exception.")) 311 )
294 312
295 self.__tabWidget.setCurrentWidget(self.glvWidget) 313 self.__tabWidget.setCurrentWidget(self.glvWidget)
296 314
297 self.__doDebuggersListUpdate = True 315 self.__doDebuggersListUpdate = True
298 316
299 self.__mainSplitter.setSizes([100, 700]) 317 self.__mainSplitter.setSizes([100, 700])
300 318
301 self.currentStack = None 319 self.currentStack = None
302 self.framenr = 0 320 self.framenr = 0
303 321
304 self.__autoViewSource = Preferences.getDebugger("AutoViewSourceCode") 322 self.__autoViewSource = Preferences.getDebugger("AutoViewSourceCode")
305 self.sourceButton.setVisible(not self.__autoViewSource) 323 self.sourceButton.setVisible(not self.__autoViewSource)
306 324
307 # connect some debug server signals 325 # connect some debug server signals
308 self.debugServer.clientStack.connect( 326 self.debugServer.clientStack.connect(self.handleClientStack)
309 self.handleClientStack) 327 self.debugServer.clientThreadList.connect(self.__addThreadList)
310 self.debugServer.clientThreadList.connect( 328 self.debugServer.clientDebuggerId.connect(self.__clientDebuggerId)
311 self.__addThreadList) 329 self.debugServer.passiveDebugStarted.connect(self.handleDebuggingStarted)
312 self.debugServer.clientDebuggerId.connect( 330 self.debugServer.clientLine.connect(self.__clientLine)
313 self.__clientDebuggerId) 331 self.debugServer.clientSyntaxError.connect(self.__clientSyntaxError)
332 self.debugServer.clientException.connect(self.__clientException)
333 self.debugServer.clientExit.connect(self.__clientExit)
334 self.debugServer.clientDisconnected.connect(self.__removeDebugger)
335
336 self.debugServer.clientException.connect(self.exceptionLogger.addException)
314 self.debugServer.passiveDebugStarted.connect( 337 self.debugServer.passiveDebugStarted.connect(
315 self.handleDebuggingStarted) 338 self.exceptionLogger.debuggingStarted
316 self.debugServer.clientLine.connect( 339 )
317 self.__clientLine) 340
318 self.debugServer.clientSyntaxError.connect( 341 self.debugServer.clientLine.connect(self.breakpointViewer.highlightBreakpoint)
319 self.__clientSyntaxError) 342
320 self.debugServer.clientException.connect(
321 self.__clientException)
322 self.debugServer.clientExit.connect(
323 self.__clientExit)
324 self.debugServer.clientDisconnected.connect(
325 self.__removeDebugger)
326
327 self.debugServer.clientException.connect(
328 self.exceptionLogger.addException)
329 self.debugServer.passiveDebugStarted.connect(
330 self.exceptionLogger.debuggingStarted)
331
332 self.debugServer.clientLine.connect(
333 self.breakpointViewer.highlightBreakpoint)
334
335 def handlePreferencesChanged(self): 343 def handlePreferencesChanged(self):
336 """ 344 """
337 Public slot to handle the preferencesChanged signal. 345 Public slot to handle the preferencesChanged signal.
338 """ 346 """
339 self.__autoViewSource = Preferences.getDebugger("AutoViewSourceCode") 347 self.__autoViewSource = Preferences.getDebugger("AutoViewSourceCode")
340 self.sourceButton.setVisible(not self.__autoViewSource) 348 self.sourceButton.setVisible(not self.__autoViewSource)
341 349
342 def setDebugger(self, debugUI): 350 def setDebugger(self, debugUI):
343 """ 351 """
344 Public method to set a reference to the Debug UI. 352 Public method to set a reference to the Debug UI.
345 353
346 @param debugUI reference to the DebugUI object 354 @param debugUI reference to the DebugUI object
347 @type DebugUI 355 @type DebugUI
348 """ 356 """
349 self.debugUI = debugUI 357 self.debugUI = debugUI
350 self.callStackViewer.setDebugger(debugUI) 358 self.callStackViewer.setDebugger(debugUI)
351 359
352 # connect some debugUI signals 360 # connect some debugUI signals
353 self.debugUI.clientStack.connect(self.handleClientStack) 361 self.debugUI.clientStack.connect(self.handleClientStack)
354 self.debugUI.debuggingStarted.connect( 362 self.debugUI.debuggingStarted.connect(self.exceptionLogger.debuggingStarted)
355 self.exceptionLogger.debuggingStarted) 363 self.debugUI.debuggingStarted.connect(self.handleDebuggingStarted)
356 self.debugUI.debuggingStarted.connect( 364
357 self.handleDebuggingStarted)
358
359 def handleResetUI(self, fullReset): 365 def handleResetUI(self, fullReset):
360 """ 366 """
361 Public method to reset the viewer. 367 Public method to reset the viewer.
362 368
363 @param fullReset flag indicating a full reset is required 369 @param fullReset flag indicating a full reset is required
364 @type bool 370 @type bool
365 """ 371 """
366 self.globalsViewer.handleResetUI() 372 self.globalsViewer.handleResetUI()
367 self.localsViewer.handleResetUI() 373 self.localsViewer.handleResetUI()
373 self.__tabWidget.setCurrentWidget(self.glvWidget) 379 self.__tabWidget.setCurrentWidget(self.glvWidget)
374 self.breakpointViewer.handleResetUI() 380 self.breakpointViewer.handleResetUI()
375 if fullReset: 381 if fullReset:
376 self.__debuggersList.clear() 382 self.__debuggersList.clear()
377 self.disassemblyViewer.clear() 383 self.disassemblyViewer.clear()
378 384
379 def initCallStackViewer(self, projectMode): 385 def initCallStackViewer(self, projectMode):
380 """ 386 """
381 Public method to initialize the call stack viewer. 387 Public method to initialize the call stack viewer.
382 388
383 @param projectMode flag indicating to enable the project mode 389 @param projectMode flag indicating to enable the project mode
384 @type bool 390 @type bool
385 """ 391 """
386 self.callStackViewer.clear() 392 self.callStackViewer.clear()
387 self.callStackViewer.setProjectMode(projectMode) 393 self.callStackViewer.setProjectMode(projectMode)
388 394
389 def isCallTraceEnabled(self): 395 def isCallTraceEnabled(self):
390 """ 396 """
391 Public method to get the state of the call trace function. 397 Public method to get the state of the call trace function.
392 398
393 @return flag indicating the state of the call trace function 399 @return flag indicating the state of the call trace function
394 @rtype bool 400 @rtype bool
395 """ 401 """
396 return self.callTraceViewer.isCallTraceEnabled() 402 return self.callTraceViewer.isCallTraceEnabled()
397 403
398 def clearCallTrace(self): 404 def clearCallTrace(self):
399 """ 405 """
400 Public method to clear the recorded call trace. 406 Public method to clear the recorded call trace.
401 """ 407 """
402 self.callTraceViewer.clear() 408 self.callTraceViewer.clear()
403 409
404 def setCallTraceToProjectMode(self, enabled): 410 def setCallTraceToProjectMode(self, enabled):
405 """ 411 """
406 Public slot to set the call trace viewer to project mode. 412 Public slot to set the call trace viewer to project mode.
407 413
408 In project mode the call trace info is shown with project relative 414 In project mode the call trace info is shown with project relative
409 path names. 415 path names.
410 416
411 @param enabled flag indicating to enable the project mode 417 @param enabled flag indicating to enable the project mode
412 @type bool 418 @type bool
413 """ 419 """
414 self.callTraceViewer.setProjectMode(enabled) 420 self.callTraceViewer.setProjectMode(enabled)
415 421
416 def showVariables(self, vlist, showGlobals): 422 def showVariables(self, vlist, showGlobals):
417 """ 423 """
418 Public method to show the variables in the respective window. 424 Public method to show the variables in the respective window.
419 425
420 @param vlist list of variables to display 426 @param vlist list of variables to display
421 @type list 427 @type list
422 @param showGlobals flag indicating global/local state 428 @param showGlobals flag indicating global/local state
423 @type bool 429 @type bool
424 """ 430 """
425 if showGlobals: 431 if showGlobals:
426 self.globalsViewer.showVariables(vlist, self.framenr) 432 self.globalsViewer.showVariables(vlist, self.framenr)
427 else: 433 else:
428 self.localsViewer.showVariables(vlist, self.framenr) 434 self.localsViewer.showVariables(vlist, self.framenr)
429 435
430 def showVariable(self, vlist, showGlobals): 436 def showVariable(self, vlist, showGlobals):
431 """ 437 """
432 Public method to show the variables in the respective window. 438 Public method to show the variables in the respective window.
433 439
434 @param vlist list of variables to display 440 @param vlist list of variables to display
435 @type list 441 @type list
436 @param showGlobals flag indicating global/local state 442 @param showGlobals flag indicating global/local state
437 @type bool 443 @type bool
438 """ 444 """
439 if showGlobals: 445 if showGlobals:
440 self.globalsViewer.showVariable(vlist) 446 self.globalsViewer.showVariable(vlist)
441 else: 447 else:
442 self.localsViewer.showVariable(vlist) 448 self.localsViewer.showVariable(vlist)
443 449
444 def showVariablesTab(self, showGlobals): 450 def showVariablesTab(self, showGlobals):
445 """ 451 """
446 Public method to make a variables tab visible. 452 Public method to make a variables tab visible.
447 453
448 @param showGlobals flag indicating global/local state 454 @param showGlobals flag indicating global/local state
449 @type bool 455 @type bool
450 """ 456 """
451 if showGlobals: 457 if showGlobals:
452 self.__tabWidget.setCurrentWidget(self.glvWidget) 458 self.__tabWidget.setCurrentWidget(self.glvWidget)
453 else: 459 else:
454 self.__tabWidget.setCurrentWidget(self.lvWidget) 460 self.__tabWidget.setCurrentWidget(self.lvWidget)
455 461
456 def handleClientStack(self, stack, debuggerId): 462 def handleClientStack(self, stack, debuggerId):
457 """ 463 """
458 Public slot to show the call stack of the program being debugged. 464 Public slot to show the call stack of the program being debugged.
459 465
460 @param stack list of tuples with call stack data (file name, 466 @param stack list of tuples with call stack data (file name,
461 line number, function name, formatted argument/values list) 467 line number, function name, formatted argument/values list)
462 @type list of tuples of (str, str, str, str) 468 @type list of tuples of (str, str, str, str)
463 @param debuggerId ID of the debugger backend 469 @param debuggerId ID of the debugger backend
464 @type str 470 @type str
470 self.currentStack = stack 476 self.currentStack = stack
471 self.sourceButton.setEnabled(len(stack) > 0) 477 self.sourceButton.setEnabled(len(stack) > 0)
472 for s in stack: 478 for s in stack:
473 # just show base filename to make it readable 479 # just show base filename to make it readable
474 s = (os.path.basename(s[0]), s[1], s[2]) 480 s = (os.path.basename(s[0]), s[1], s[2])
475 self.stackComboBox.addItem('{0}:{1}:{2}'.format(*s)) 481 self.stackComboBox.addItem("{0}:{1}:{2}".format(*s))
476 self.stackComboBox.blockSignals(block) 482 self.stackComboBox.blockSignals(block)
477 483
478 def __clientLine(self, fn, line, debuggerId, threadName): 484 def __clientLine(self, fn, line, debuggerId, threadName):
479 """ 485 """
480 Private method to handle a change to the current line. 486 Private method to handle a change to the current line.
481 487
482 @param fn filename 488 @param fn filename
483 @type str 489 @type str
484 @param line linenumber 490 @param line linenumber
485 @type int 491 @type int
486 @param debuggerId ID of the debugger backend 492 @param debuggerId ID of the debugger backend
490 """ 496 """
491 self.__setDebuggerIconAndState(debuggerId, "broken") 497 self.__setDebuggerIconAndState(debuggerId, "broken")
492 self.__setThreadIconAndState(debuggerId, threadName, "broken") 498 self.__setThreadIconAndState(debuggerId, threadName, "broken")
493 if debuggerId != self.getSelectedDebuggerId(): 499 if debuggerId != self.getSelectedDebuggerId():
494 self.__setCurrentDebugger(debuggerId) 500 self.__setCurrentDebugger(debuggerId)
495 501
496 @pyqtSlot(str, int, str, bool, str) 502 @pyqtSlot(str, int, str, bool, str)
497 def __clientExit(self, program, status, message, quiet, debuggerId): 503 def __clientExit(self, program, status, message, quiet, debuggerId):
498 """ 504 """
499 Private method to handle the debugged program terminating. 505 Private method to handle the debugged program terminating.
500 506
501 @param program name of the exited program 507 @param program name of the exited program
502 @type str 508 @type str
503 @param status exit code of the debugged program 509 @param status exit code of the debugged program
504 @type int 510 @type int
505 @param message exit message of the debugged program 511 @param message exit message of the debugged program
517 self.setGlobalsFilter() 523 self.setGlobalsFilter()
518 self.setLocalsFilter() 524 self.setLocalsFilter()
519 self.sourceButton.setEnabled(False) 525 self.sourceButton.setEnabled(False)
520 self.currentStack = None 526 self.currentStack = None
521 self.stackComboBox.clear() 527 self.stackComboBox.clear()
522 528
523 self.__removeDebugger(debuggerId) 529 self.__removeDebugger(debuggerId)
524 530
525 def __clientSyntaxError(self, message, filename, lineNo, characterNo, 531 def __clientSyntaxError(
526 debuggerId, threadName): 532 self, message, filename, lineNo, characterNo, debuggerId, threadName
533 ):
527 """ 534 """
528 Private method to handle a syntax error in the debugged program. 535 Private method to handle a syntax error in the debugged program.
529 536
530 @param message message of the syntax error 537 @param message message of the syntax error
531 @type str 538 @type str
532 @param filename translated filename of the syntax error position 539 @param filename translated filename of the syntax error position
533 @type str 540 @type str
534 @param lineNo line number of the syntax error position 541 @param lineNo line number of the syntax error position
540 @param threadName name of the thread signaling the event 547 @param threadName name of the thread signaling the event
541 @type str 548 @type str
542 """ 549 """
543 self.__setDebuggerIconAndState(debuggerId, "syntax") 550 self.__setDebuggerIconAndState(debuggerId, "syntax")
544 self.__setThreadIconAndState(debuggerId, threadName, "syntax") 551 self.__setThreadIconAndState(debuggerId, threadName, "syntax")
545 552
546 def __clientException(self, exceptionType, exceptionMessage, stackTrace, 553 def __clientException(
547 debuggerId, threadName): 554 self, exceptionType, exceptionMessage, stackTrace, debuggerId, threadName
555 ):
548 """ 556 """
549 Private method to handle an exception of the debugged program. 557 Private method to handle an exception of the debugged program.
550 558
551 @param exceptionType type of exception raised 559 @param exceptionType type of exception raised
552 @type str 560 @type str
553 @param exceptionMessage message given by the exception 561 @param exceptionMessage message given by the exception
554 @type (str 562 @type (str
555 @param stackTrace list of stack entries 563 @param stackTrace list of stack entries
559 @param threadName name of the thread signaling the event 567 @param threadName name of the thread signaling the event
560 @type str 568 @type str
561 """ 569 """
562 self.__setDebuggerIconAndState(debuggerId, "exception") 570 self.__setDebuggerIconAndState(debuggerId, "exception")
563 self.__setThreadIconAndState(debuggerId, threadName, "exception") 571 self.__setThreadIconAndState(debuggerId, threadName, "exception")
564 572
565 def setVariablesFilter(self, globalsFilter, localsFilter): 573 def setVariablesFilter(self, globalsFilter, localsFilter):
566 """ 574 """
567 Public slot to set the local variables filter. 575 Public slot to set the local variables filter.
568 576
569 @param globalsFilter filter list for global variable types 577 @param globalsFilter filter list for global variable types
570 @type list of str 578 @type list of str
571 @param localsFilter filter list for local variable types 579 @param localsFilter filter list for local variable types
572 @type list of str 580 @type list of str
573 """ 581 """
574 self.__globalsFilter = globalsFilter 582 self.__globalsFilter = globalsFilter
575 self.__localsFilter = localsFilter 583 self.__localsFilter = localsFilter
576 584
577 def __showSource(self): 585 def __showSource(self):
578 """ 586 """
579 Private slot to handle the source button press to show the selected 587 Private slot to handle the source button press to show the selected
580 file. 588 file.
581 """ 589 """
582 index = self.stackComboBox.currentIndex() 590 index = self.stackComboBox.currentIndex()
583 if index > -1 and self.currentStack: 591 if index > -1 and self.currentStack:
584 s = self.currentStack[index] 592 s = self.currentStack[index]
585 self.sourceFile.emit(s[0], int(s[1])) 593 self.sourceFile.emit(s[0], int(s[1]))
586 594
587 def __frameSelected(self, frmnr): 595 def __frameSelected(self, frmnr):
588 """ 596 """
589 Private slot to handle the selection of a new stack frame number. 597 Private slot to handle the selection of a new stack frame number.
590 598
591 @param frmnr frame number (0 is the current frame) 599 @param frmnr frame number (0 is the current frame)
592 @type int 600 @type int
593 """ 601 """
594 if frmnr >= 0: 602 if frmnr >= 0:
595 self.framenr = frmnr 603 self.framenr = frmnr
596 if self.debugServer.isDebugging(): 604 if self.debugServer.isDebugging():
597 self.debugServer.remoteClientVariables( 605 self.debugServer.remoteClientVariables(
598 self.getSelectedDebuggerId(), 0, self.__localsFilter, 606 self.getSelectedDebuggerId(), 0, self.__localsFilter, frmnr
599 frmnr) 607 )
600 608
601 if self.__autoViewSource: 609 if self.__autoViewSource:
602 self.__showSource() 610 self.__showSource()
603 611
604 def setGlobalsFilter(self): 612 def setGlobalsFilter(self):
605 """ 613 """
606 Public slot to set the global variable filter. 614 Public slot to set the global variable filter.
607 """ 615 """
608 if self.debugServer.isDebugging(): 616 if self.debugServer.isDebugging():
609 filterStr = self.globalsFilterEdit.text() 617 filterStr = self.globalsFilterEdit.text()
610 self.debugServer.remoteClientSetFilter( 618 self.debugServer.remoteClientSetFilter(
611 self.getSelectedDebuggerId(), 1, filterStr) 619 self.getSelectedDebuggerId(), 1, filterStr
620 )
612 self.debugServer.remoteClientVariables( 621 self.debugServer.remoteClientVariables(
613 self.getSelectedDebuggerId(), 2, self.__globalsFilter) 622 self.getSelectedDebuggerId(), 2, self.__globalsFilter
614 623 )
624
615 def setLocalsFilter(self): 625 def setLocalsFilter(self):
616 """ 626 """
617 Public slot to set the local variable filter. 627 Public slot to set the local variable filter.
618 """ 628 """
619 if self.debugServer.isDebugging(): 629 if self.debugServer.isDebugging():
620 filterStr = self.localsFilterEdit.text() 630 filterStr = self.localsFilterEdit.text()
621 self.debugServer.remoteClientSetFilter( 631 self.debugServer.remoteClientSetFilter(
622 self.getSelectedDebuggerId(), 0, filterStr) 632 self.getSelectedDebuggerId(), 0, filterStr
633 )
623 if self.currentStack: 634 if self.currentStack:
624 self.debugServer.remoteClientVariables( 635 self.debugServer.remoteClientVariables(
625 self.getSelectedDebuggerId(), 0, self.__localsFilter, 636 self.getSelectedDebuggerId(), 0, self.__localsFilter, self.framenr
626 self.framenr) 637 )
627 638
628 def handleDebuggingStarted(self): 639 def handleDebuggingStarted(self):
629 """ 640 """
630 Public slot to handle the start of a debugging session. 641 Public slot to handle the start of a debugging session.
631 642
632 This slot sets the variables filter expressions. 643 This slot sets the variables filter expressions.
633 """ 644 """
634 self.setGlobalsFilter() 645 self.setGlobalsFilter()
635 self.setLocalsFilter() 646 self.setLocalsFilter()
636 self.showVariablesTab(False) 647 self.showVariablesTab(False)
637 648
638 self.disassemblyViewer.clear() 649 self.disassemblyViewer.clear()
639 650
640 def currentWidget(self): 651 def currentWidget(self):
641 """ 652 """
642 Public method to get a reference to the current widget. 653 Public method to get a reference to the current widget.
643 654
644 @return reference to the current widget 655 @return reference to the current widget
645 @rtype QWidget 656 @rtype QWidget
646 """ 657 """
647 return self.__tabWidget.currentWidget() 658 return self.__tabWidget.currentWidget()
648 659
649 def setCurrentWidget(self, widget): 660 def setCurrentWidget(self, widget):
650 """ 661 """
651 Public slot to set the current page based on the given widget. 662 Public slot to set the current page based on the given widget.
652 663
653 @param widget reference to the widget 664 @param widget reference to the widget
654 @type QWidget 665 @type QWidget
655 """ 666 """
656 self.__tabWidget.setCurrentWidget(widget) 667 self.__tabWidget.setCurrentWidget(widget)
657 668
658 def __callStackFrameSelected(self, frameNo): 669 def __callStackFrameSelected(self, frameNo):
659 """ 670 """
660 Private slot to handle the selection of a call stack entry of the 671 Private slot to handle the selection of a call stack entry of the
661 call stack viewer. 672 call stack viewer.
662 673
663 @param frameNo frame number (index) of the selected entry 674 @param frameNo frame number (index) of the selected entry
664 @type int 675 @type int
665 """ 676 """
666 if frameNo >= 0: 677 if frameNo >= 0:
667 self.stackComboBox.setCurrentIndex(frameNo) 678 self.stackComboBox.setCurrentIndex(frameNo)
668 679
669 def __debuggerSelected(self, current, previous): 680 def __debuggerSelected(self, current, previous):
670 """ 681 """
671 Private slot to handle the selection of a debugger backend in the 682 Private slot to handle the selection of a debugger backend in the
672 debuggers list. 683 debuggers list.
673 684
674 @param current reference to the new current item 685 @param current reference to the new current item
675 @type QTreeWidgetItem 686 @type QTreeWidgetItem
676 @param previous reference to the previous current item 687 @param previous reference to the previous current item
677 @type QTreeWidgetItem 688 @type QTreeWidgetItem
678 """ 689 """
683 self.globalsViewer.handleResetUI() 694 self.globalsViewer.handleResetUI()
684 self.localsViewer.handleResetUI() 695 self.localsViewer.handleResetUI()
685 self.currentStack = None 696 self.currentStack = None
686 self.stackComboBox.clear() 697 self.stackComboBox.clear()
687 self.callStackViewer.clear() 698 self.callStackViewer.clear()
688 699
689 self.debugServer.remoteSetThread(debuggerId, -1) 700 self.debugServer.remoteSetThread(debuggerId, -1)
690 self.__showSource() 701 self.__showSource()
691 else: 702 else:
692 # it is a thread item 703 # it is a thread item
693 tid = current.data(0, self.ThreadIdRole) 704 tid = current.data(0, self.ThreadIdRole)
694 self.debugServer.remoteSetThread( 705 self.debugServer.remoteSetThread(self.getSelectedDebuggerId(), tid)
695 self.getSelectedDebuggerId(), tid) 706
696
697 def __clientDebuggerId(self, debuggerId): 707 def __clientDebuggerId(self, debuggerId):
698 """ 708 """
699 Private slot to receive the ID of a newly connected debugger backend. 709 Private slot to receive the ID of a newly connected debugger backend.
700 710
701 @param debuggerId ID of a newly connected debugger backend 711 @param debuggerId ID of a newly connected debugger backend
702 @type str 712 @type str
703 """ 713 """
704 itm = QTreeWidgetItem(self.__debuggersList, [debuggerId]) 714 itm = QTreeWidgetItem(self.__debuggersList, [debuggerId])
705 if self.__debuggersList.topLevelItemCount() > 1: 715 if self.__debuggersList.topLevelItemCount() > 1:
706 self.debugUI.showNotification( 716 self.debugUI.showNotification(
707 self.tr("<p>Debugger with ID <b>{0}</b> has been connected." 717 self.tr(
708 "</p>") 718 "<p>Debugger with ID <b>{0}</b> has been connected." "</p>"
709 .format(debuggerId)) 719 ).format(debuggerId)
710 720 )
721
711 self.__debuggersList.header().resizeSections( 722 self.__debuggersList.header().resizeSections(
712 QHeaderView.ResizeMode.ResizeToContents) 723 QHeaderView.ResizeMode.ResizeToContents
713 724 )
725
714 if self.__debuggersList.topLevelItemCount() == 1: 726 if self.__debuggersList.topLevelItemCount() == 1:
715 # it is the only item, select it as the current one 727 # it is the only item, select it as the current one
716 self.__debuggersList.setCurrentItem(itm) 728 self.__debuggersList.setCurrentItem(itm)
717 729
718 def __setCurrentDebugger(self, debuggerId): 730 def __setCurrentDebugger(self, debuggerId):
719 """ 731 """
720 Private method to set the current debugger based on the given ID. 732 Private method to set the current debugger based on the given ID.
721 733
722 @param debuggerId ID of the debugger to set as current debugger 734 @param debuggerId ID of the debugger to set as current debugger
723 @type str 735 @type str
724 """ 736 """
725 debuggerItems = self.__debuggersList.findItems( 737 debuggerItems = self.__debuggersList.findItems(
726 debuggerId, Qt.MatchFlag.MatchExactly) 738 debuggerId, Qt.MatchFlag.MatchExactly
739 )
727 if debuggerItems: 740 if debuggerItems:
728 debuggerItem = debuggerItems[0] 741 debuggerItem = debuggerItems[0]
729 currentItem = self.__debuggersList.currentItem() 742 currentItem = self.__debuggersList.currentItem()
730 if currentItem is debuggerItem: 743 if currentItem is debuggerItem:
731 # nothing to do 744 # nothing to do
732 return 745 return
733 746
734 if currentItem: 747 if currentItem:
735 currentParent = currentItem.parent() 748 currentParent = currentItem.parent()
736 else: 749 else:
737 currentParent = None 750 currentParent = None
738 if currentParent is None: 751 if currentParent is None:
741 elif currentParent is debuggerItem: 754 elif currentParent is debuggerItem:
742 # nothing to do 755 # nothing to do
743 return 756 return
744 else: 757 else:
745 self.__debuggersList.setCurrentItem(debuggerItem) 758 self.__debuggersList.setCurrentItem(debuggerItem)
746 759
747 def isOnlyDebugger(self): 760 def isOnlyDebugger(self):
748 """ 761 """
749 Public method to test, if only one debugger is connected. 762 Public method to test, if only one debugger is connected.
750 763
751 @return flag indicating that only one debugger is connected 764 @return flag indicating that only one debugger is connected
752 @rtype bool 765 @rtype bool
753 """ 766 """
754 return self.__debuggersList.topLevelItemCount() == 1 767 return self.__debuggersList.topLevelItemCount() == 1
755 768
756 def getSelectedDebuggerId(self): 769 def getSelectedDebuggerId(self):
757 """ 770 """
758 Public method to get the currently selected debugger ID. 771 Public method to get the currently selected debugger ID.
759 772
760 @return selected debugger ID 773 @return selected debugger ID
761 @rtype str 774 @rtype str
762 """ 775 """
763 itm = self.__debuggersList.currentItem() 776 itm = self.__debuggersList.currentItem()
764 if itm: 777 if itm:
768 else: 781 else:
769 # it is a thread item 782 # it is a thread item
770 return itm.parent().text(0) 783 return itm.parent().text(0)
771 else: 784 else:
772 return "" 785 return ""
773 786
774 def getSelectedDebuggerState(self): 787 def getSelectedDebuggerState(self):
775 """ 788 """
776 Public method to get the currently selected debugger's state. 789 Public method to get the currently selected debugger's state.
777 790
778 @return selected debugger's state (broken, exception, running) 791 @return selected debugger's state (broken, exception, running)
779 @rtype str 792 @rtype str
780 """ 793 """
781 itm = self.__debuggersList.currentItem() 794 itm = self.__debuggersList.currentItem()
782 if itm: 795 if itm:
786 else: 799 else:
787 # it is a thread item 800 # it is a thread item
788 return itm.parent().data(0, self.DebuggerStateRole) 801 return itm.parent().data(0, self.DebuggerStateRole)
789 else: 802 else:
790 return "" 803 return ""
791 804
792 def __setDebuggerIconAndState(self, debuggerId, state): 805 def __setDebuggerIconAndState(self, debuggerId, state):
793 """ 806 """
794 Private method to set the icon for a specific debugger ID. 807 Private method to set the icon for a specific debugger ID.
795 808
796 @param debuggerId ID of the debugger backend (empty ID means the 809 @param debuggerId ID of the debugger backend (empty ID means the
797 currently selected one) 810 currently selected one)
798 @type str 811 @type str
799 @param state state of the debugger (broken, exception, running) 812 @param state state of the debugger (broken, exception, running)
800 @type str 813 @type str
801 """ 814 """
802 debuggerItem = None 815 debuggerItem = None
803 if debuggerId: 816 if debuggerId:
804 foundItems = self.__debuggersList.findItems( 817 foundItems = self.__debuggersList.findItems(
805 debuggerId, Qt.MatchFlag.MatchExactly) 818 debuggerId, Qt.MatchFlag.MatchExactly
819 )
806 if foundItems: 820 if foundItems:
807 debuggerItem = foundItems[0] 821 debuggerItem = foundItems[0]
808 if debuggerItem is None: 822 if debuggerItem is None:
809 debuggerItem = self.__debuggersList.currentItem() 823 debuggerItem = self.__debuggersList.currentItem()
810 if debuggerItem is not None: 824 if debuggerItem is not None:
817 except KeyError: 831 except KeyError:
818 stateText = self.tr("unknown state ({0})").format(state) 832 stateText = self.tr("unknown state ({0})").format(state)
819 debuggerItem.setIcon(0, UI.PixmapCache.getIcon(iconName)) 833 debuggerItem.setIcon(0, UI.PixmapCache.getIcon(iconName))
820 debuggerItem.setData(0, self.DebuggerStateRole, state) 834 debuggerItem.setData(0, self.DebuggerStateRole, state)
821 debuggerItem.setText(1, stateText) 835 debuggerItem.setText(1, stateText)
822 836
823 self.__debuggersList.header().resizeSections( 837 self.__debuggersList.header().resizeSections(
824 QHeaderView.ResizeMode.ResizeToContents) 838 QHeaderView.ResizeMode.ResizeToContents
825 839 )
840
826 def __removeDebugger(self, debuggerId): 841 def __removeDebugger(self, debuggerId):
827 """ 842 """
828 Private method to remove a debugger given its ID. 843 Private method to remove a debugger given its ID.
829 844
830 @param debuggerId ID of the debugger to be removed from the list 845 @param debuggerId ID of the debugger to be removed from the list
831 @type str 846 @type str
832 """ 847 """
833 foundItems = self.__debuggersList.findItems( 848 foundItems = self.__debuggersList.findItems(
834 debuggerId, Qt.MatchFlag.MatchExactly) 849 debuggerId, Qt.MatchFlag.MatchExactly
850 )
835 if foundItems: 851 if foundItems:
836 index = self.__debuggersList.indexOfTopLevelItem(foundItems[0]) 852 index = self.__debuggersList.indexOfTopLevelItem(foundItems[0])
837 itm = self.__debuggersList.takeTopLevelItem(index) 853 itm = self.__debuggersList.takeTopLevelItem(index)
838 # __IGNORE_WARNING__ 854 # __IGNORE_WARNING__
839 del itm 855 del itm
840 856
841 def __addThreadList(self, currentID, threadList, debuggerId): 857 def __addThreadList(self, currentID, threadList, debuggerId):
842 """ 858 """
843 Private method to add the list of threads to a debugger entry. 859 Private method to add the list of threads to a debugger entry.
844 860
845 @param currentID id of the current thread 861 @param currentID id of the current thread
846 @type int 862 @type int
847 @param threadList list of dictionaries containing the thread data 863 @param threadList list of dictionaries containing the thread data
848 @type list of dict 864 @type list of dict
849 @param debuggerId ID of the debugger backend 865 @param debuggerId ID of the debugger backend
850 @type str 866 @type str
851 """ 867 """
852 debugStatus = -1 # i.e. running 868 debugStatus = -1 # i.e. running
853 869
854 debuggerItems = self.__debuggersList.findItems( 870 debuggerItems = self.__debuggersList.findItems(
855 debuggerId, Qt.MatchFlag.MatchExactly) 871 debuggerId, Qt.MatchFlag.MatchExactly
872 )
856 if debuggerItems: 873 if debuggerItems:
857 debuggerItem = debuggerItems[0] 874 debuggerItem = debuggerItems[0]
858 875
859 currentItem = self.__debuggersList.currentItem() 876 currentItem = self.__debuggersList.currentItem()
860 if currentItem.parent() is debuggerItem: 877 if currentItem.parent() is debuggerItem:
861 currentChild = currentItem.text(0) 878 currentChild = currentItem.text(0)
862 else: 879 else:
863 currentChild = "" 880 currentChild = ""
864 self.__doDebuggersListUpdate = False 881 self.__doDebuggersListUpdate = False
865 debuggerItem.takeChildren() 882 debuggerItem.takeChildren()
866 for thread in threadList: 883 for thread in threadList:
867 if thread.get('except', False): 884 if thread.get("except", False):
868 stateText = DebugViewer.StateMessage["exception"] 885 stateText = DebugViewer.StateMessage["exception"]
869 iconName = DebugViewer.StateIcon["exception"] 886 iconName = DebugViewer.StateIcon["exception"]
870 debugStatus = 1 887 debugStatus = 1
871 elif thread['broken']: 888 elif thread["broken"]:
872 stateText = DebugViewer.StateMessage["broken"] 889 stateText = DebugViewer.StateMessage["broken"]
873 iconName = DebugViewer.StateIcon["broken"] 890 iconName = DebugViewer.StateIcon["broken"]
874 if debugStatus < 1: 891 if debugStatus < 1:
875 debugStatus = 0 892 debugStatus = 0
876 else: 893 else:
877 stateText = DebugViewer.StateMessage["running"] 894 stateText = DebugViewer.StateMessage["running"]
878 iconName = DebugViewer.StateIcon["running"] 895 iconName = DebugViewer.StateIcon["running"]
879 itm = QTreeWidgetItem(debuggerItem, 896 itm = QTreeWidgetItem(debuggerItem, [thread["name"], stateText])
880 [thread['name'], stateText]) 897 itm.setData(0, self.ThreadIdRole, thread["id"])
881 itm.setData(0, self.ThreadIdRole, thread['id'])
882 itm.setIcon(0, UI.PixmapCache.getIcon(iconName)) 898 itm.setIcon(0, UI.PixmapCache.getIcon(iconName))
883 if currentChild == thread['name']: 899 if currentChild == thread["name"]:
884 self.__debuggersList.setCurrentItem(itm) 900 self.__debuggersList.setCurrentItem(itm)
885 if thread['id'] == currentID: 901 if thread["id"] == currentID:
886 font = debuggerItem.font(0) 902 font = debuggerItem.font(0)
887 font.setItalic(True) 903 font.setItalic(True)
888 itm.setFont(0, font) 904 itm.setFont(0, font)
889 905
890 debuggerItem.setExpanded(debuggerItem.childCount() > 0) 906 debuggerItem.setExpanded(debuggerItem.childCount() > 0)
891 907
892 self.__debuggersList.header().resizeSections( 908 self.__debuggersList.header().resizeSections(
893 QHeaderView.ResizeMode.ResizeToContents) 909 QHeaderView.ResizeMode.ResizeToContents
910 )
894 self.__debuggersList.header().setStretchLastSection(True) 911 self.__debuggersList.header().setStretchLastSection(True)
895 self.__doDebuggersListUpdate = True 912 self.__doDebuggersListUpdate = True
896 913
897 if debugStatus == -1: 914 if debugStatus == -1:
898 debuggerState = "running" 915 debuggerState = "running"
899 elif debugStatus == 0: 916 elif debugStatus == 0:
900 debuggerState = "broken" 917 debuggerState = "broken"
901 else: 918 else:
902 debuggerState = "exception" 919 debuggerState = "exception"
903 self.__setDebuggerIconAndState(debuggerId, debuggerState) 920 self.__setDebuggerIconAndState(debuggerId, debuggerState)
904 921
905 def __setThreadIconAndState(self, debuggerId, threadName, state): 922 def __setThreadIconAndState(self, debuggerId, threadName, state):
906 """ 923 """
907 Private method to set the icon for a specific thread name and 924 Private method to set the icon for a specific thread name and
908 debugger ID. 925 debugger ID.
909 926
910 @param debuggerId ID of the debugger backend (empty ID means the 927 @param debuggerId ID of the debugger backend (empty ID means the
911 currently selected one) 928 currently selected one)
912 @type str 929 @type str
913 @param threadName name of the thread signaling the event 930 @param threadName name of the thread signaling the event
914 @type str 931 @type str
916 @type str 933 @type str
917 """ 934 """
918 debuggerItem = None 935 debuggerItem = None
919 if debuggerId: 936 if debuggerId:
920 foundItems = self.__debuggersList.findItems( 937 foundItems = self.__debuggersList.findItems(
921 debuggerId, Qt.MatchFlag.MatchExactly) 938 debuggerId, Qt.MatchFlag.MatchExactly
939 )
922 if foundItems: 940 if foundItems:
923 debuggerItem = foundItems[0] 941 debuggerItem = foundItems[0]
924 if debuggerItem is None: 942 if debuggerItem is None:
925 debuggerItem = self.__debuggersList.currentItem() 943 debuggerItem = self.__debuggersList.currentItem()
926 if debuggerItem is not None: 944 if debuggerItem is not None:
928 childItem = debuggerItem.child(index) 946 childItem = debuggerItem.child(index)
929 if childItem.text(0) == threadName: 947 if childItem.text(0) == threadName:
930 break 948 break
931 else: 949 else:
932 childItem = None 950 childItem = None
933 951
934 if childItem is not None: 952 if childItem is not None:
935 try: 953 try:
936 iconName = DebugViewer.StateIcon[state] 954 iconName = DebugViewer.StateIcon[state]
937 except KeyError: 955 except KeyError:
938 iconName = "question" 956 iconName = "question"
940 stateText = DebugViewer.StateMessage[state] 958 stateText = DebugViewer.StateMessage[state]
941 except KeyError: 959 except KeyError:
942 stateText = self.tr("unknown state ({0})").format(state) 960 stateText = self.tr("unknown state ({0})").format(state)
943 childItem.setIcon(0, UI.PixmapCache.getIcon(iconName)) 961 childItem.setIcon(0, UI.PixmapCache.getIcon(iconName))
944 childItem.setText(1, stateText) 962 childItem.setText(1, stateText)
945 963
946 self.__debuggersList.header().resizeSections( 964 self.__debuggersList.header().resizeSections(
947 QHeaderView.ResizeMode.ResizeToContents) 965 QHeaderView.ResizeMode.ResizeToContents
966 )

eric ide

mercurial