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() |
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 """ |
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 |