Debugger/BreakPointViewer.py

changeset 0
de9c2efb9d02
child 12
1d8dd9706f46
equal deleted inserted replaced
-1:000000000000 0:de9c2efb9d02
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2005 - 2009 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the Breakpoint viewer widget.
8 """
9
10 from PyQt4.QtCore import *
11 from PyQt4.QtGui import *
12
13 from E4Gui.E4Application import e4App
14
15 from EditBreakpointDialog import EditBreakpointDialog
16
17 class BreakPointViewer(QTreeView):
18 """
19 Class implementing the Breakpoint viewer widget.
20
21 Breakpoints will be shown with all their details. They can be modified through
22 the context menu of this widget.
23
24 @signal sourceFile(string, int) emitted to show the source of a breakpoint
25 """
26 def __init__(self, parent = None):
27 """
28 Constructor
29
30 @param parent the parent (QWidget)
31 """
32 QTreeView.__init__(self, parent)
33 self.setObjectName("BreakPointViewer")
34
35 self.__model = None
36
37 self.setItemsExpandable(False)
38 self.setRootIsDecorated(False)
39 self.setAlternatingRowColors(True)
40 self.setSelectionMode(QAbstractItemView.ExtendedSelection)
41 self.setSelectionBehavior(QAbstractItemView.SelectRows)
42
43 self.setWindowTitle(self.trUtf8("Breakpoints"))
44
45 self.setContextMenuPolicy(Qt.CustomContextMenu)
46 self.connect(self,SIGNAL('customContextMenuRequested(const QPoint &)'),
47 self.__showContextMenu)
48 self.connect(self,SIGNAL('doubleClicked(const QModelIndex &)'),
49 self.__doubleClicked)
50
51 self.__createPopupMenus()
52
53 self.condHistory = []
54 self.fnHistory = []
55 self.fnHistory.append('')
56
57 def setModel(self, model):
58 """
59 Public slot to set the breakpoint model.
60
61 @param reference to the breakpoint model (BreakPointModel)
62 """
63 self.__model = model
64
65 self.sortingModel = QSortFilterProxyModel()
66 self.sortingModel.setSourceModel(self.__model)
67 QTreeView.setModel(self, self.sortingModel)
68
69 header = self.header()
70 header.setSortIndicator(0, Qt.AscendingOrder)
71 header.setSortIndicatorShown(True)
72 header.setClickable(True)
73
74 self.setSortingEnabled(True)
75
76 self.__layoutDisplay()
77
78 def __layoutDisplay(self):
79 """
80 Private slot to perform a layout operation.
81 """
82 self.doItemsLayout()
83 self.__resizeColumns()
84 self.__resort()
85
86 def __resizeColumns(self):
87 """
88 Private slot to resize the view when items get added, edited or deleted.
89 """
90 self.header().resizeSections(QHeaderView.ResizeToContents)
91 self.header().setStretchLastSection(True)
92
93 def __resort(self):
94 """
95 Private slot to resort the tree.
96 """
97 self.model().sort(self.header().sortIndicatorSection(),
98 self.header().sortIndicatorOrder())
99
100 def __toSourceIndex(self, index):
101 """
102 Private slot to convert an index to a source index.
103
104 @param index index to be converted (QModelIndex)
105 """
106 return self.sortingModel.mapToSource(index)
107
108 def __fromSourceIndex(self, sindex):
109 """
110 Private slot to convert a source index to an index.
111
112 @param sindex source index to be converted (QModelIndex)
113 """
114 return self.sortingModel.mapFromSource(sindex)
115
116 def __setRowSelected(self, index, selected = True):
117 """
118 Private slot to select a complete row.
119
120 @param index index determining the row to be selected (QModelIndex)
121 @param selected flag indicating the action (bool)
122 """
123 if not index.isValid():
124 return
125
126 if selected:
127 flags = QItemSelectionModel.SelectionFlags(\
128 QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows)
129 else:
130 flags = QItemSelectionModel.SelectionFlags(\
131 QItemSelectionModel.Deselect | QItemSelectionModel.Rows)
132 self.selectionModel().select(index, flags)
133
134 def __createPopupMenus(self):
135 """
136 Private method to generate the popup menus.
137 """
138 self.menu = QMenu()
139 self.menu.addAction(self.trUtf8("Add"), self.__addBreak)
140 self.menu.addAction(self.trUtf8("Edit..."), self.__editBreak)
141 self.menu.addSeparator()
142 self.menu.addAction(self.trUtf8("Enable"), self.__enableBreak)
143 self.menu.addAction(self.trUtf8("Enable all"), self.__enableAllBreaks)
144 self.menu.addSeparator()
145 self.menu.addAction(self.trUtf8("Disable"), self.__disableBreak)
146 self.menu.addAction(self.trUtf8("Disable all"), self.__disableAllBreaks)
147 self.menu.addSeparator()
148 self.menu.addAction(self.trUtf8("Delete"), self.__deleteBreak)
149 self.menu.addAction(self.trUtf8("Delete all"), self.__deleteAllBreaks)
150 self.menu.addSeparator()
151 self.menu.addAction(self.trUtf8("Goto"), self.__showSource)
152 self.menu.addSeparator()
153 self.menu.addAction(self.trUtf8("Configure..."), self.__configure)
154
155 self.backMenuActions = {}
156 self.backMenu = QMenu()
157 self.backMenu.addAction(self.trUtf8("Add"), self.__addBreak)
158 self.backMenuActions["EnableAll"] = \
159 self.backMenu.addAction(self.trUtf8("Enable all"), self.__enableAllBreaks)
160 self.backMenuActions["DisableAll"] = \
161 self.backMenu.addAction(self.trUtf8("Disable all"), self.__disableAllBreaks)
162 self.backMenuActions["DeleteAll"] = \
163 self.backMenu.addAction(self.trUtf8("Delete all"), self.__deleteAllBreaks)
164 self.connect(self.backMenu, SIGNAL('aboutToShow()'), self.__showBackMenu)
165 self.backMenu.addSeparator()
166 self.backMenu.addAction(self.trUtf8("Configure..."), self.__configure)
167
168 self.multiMenu = QMenu()
169 self.multiMenu.addAction(self.trUtf8("Add"), self.__addBreak)
170 self.multiMenu.addSeparator()
171 self.multiMenu.addAction(self.trUtf8("Enable selected"),
172 self.__enableSelectedBreaks)
173 self.multiMenu.addAction(self.trUtf8("Enable all"), self.__enableAllBreaks)
174 self.multiMenu.addSeparator()
175 self.multiMenu.addAction(self.trUtf8("Disable selected"),
176 self.__disableSelectedBreaks)
177 self.multiMenu.addAction(self.trUtf8("Disable all"), self.__disableAllBreaks)
178 self.multiMenu.addSeparator()
179 self.multiMenu.addAction(self.trUtf8("Delete selected"),
180 self.__deleteSelectedBreaks)
181 self.multiMenu.addAction(self.trUtf8("Delete all"), self.__deleteAllBreaks)
182 self.multiMenu.addSeparator()
183 self.multiMenu.addAction(self.trUtf8("Configure..."), self.__configure)
184
185 def __showContextMenu(self, coord):
186 """
187 Private slot to show the context menu.
188
189 @param coord the position of the mouse pointer (QPoint)
190 """
191 cnt = self.__getSelectedItemsCount()
192 if cnt <= 1:
193 index = self.indexAt(coord)
194 if index.isValid():
195 cnt = 1
196 self.__setRowSelected(index)
197 coord = self.mapToGlobal(coord)
198 if cnt > 1:
199 self.multiMenu.popup(coord)
200 elif cnt == 1:
201 self.menu.popup(coord)
202 else:
203 self.backMenu.popup(coord)
204
205 def __clearSelection(self):
206 """
207 Private slot to clear the selection.
208 """
209 for index in self.selectedIndexes():
210 self.__setRowSelected(index, False)
211
212 def __addBreak(self):
213 """
214 Private slot to handle the add breakpoint context menu entry.
215 """
216 dlg = EditBreakpointDialog((self.fnHistory[0], None), None,
217 self.condHistory, self, modal = 1, addMode = 1,
218 filenameHistory = self.fnHistory)
219 if dlg.exec_() == QDialog.Accepted:
220 fn, line, cond, temp, enabled, count = dlg.getAddData()
221 if fn is not None:
222 if fn in self.fnHistory:
223 self.fnHistory.remove(fn)
224 self.fnHistory.insert(0, fn)
225
226 if cond:
227 if cond in self.condHistory:
228 self.condHistory.remove(cond)
229 self.condHistory.insert(0, cond)
230
231 self.__model.addBreakPoint(fn, line, (cond, temp, enabled, count))
232 self.__resizeColumns()
233 self.__resort()
234
235 def __doubleClicked(self, index):
236 """
237 Private slot to handle the double clicked signal.
238
239 @param index index of the entry that was double clicked (QModelIndex)
240 """
241 if index.isValid():
242 self.__editBreakpoint(index)
243
244 def __editBreak(self):
245 """
246 Private slot to handle the edit breakpoint context menu entry.
247 """
248 index = self.currentIndex()
249 if index.isValid():
250 self.__editBreakpoint(index)
251
252 def __editBreakpoint(self, index):
253 """
254 Private slot to edit a breakpoint.
255
256 @param index index of breakpoint to be edited (QModelIndex)
257 """
258 sindex = self.__toSourceIndex(index)
259 if sindex.isValid():
260 bp = self.__model.getBreakPointByIndex(sindex)
261 if not bp:
262 return
263
264 fn, line, cond, temp, enabled, count = bp[:6]
265
266 dlg = EditBreakpointDialog((fn, line), (cond, temp, enabled, count),
267 self.condHistory, self, modal = True)
268 if dlg.exec_() == QDialog.Accepted:
269 cond, temp, enabled, count = dlg.getData()
270 if cond:
271 if cond in self.condHistory:
272 self.condHistory.remove(cond)
273 self.condHistory.insert(0, cond)
274
275 self.__model.setBreakPointByIndex(sindex,
276 fn, line, (cond, temp, enabled, count))
277 self.__resizeColumns()
278 self.__resort()
279
280 def __setBpEnabled(self, index, enabled):
281 """
282 Private method to set the enabled status of a breakpoint.
283
284 @param index index of breakpoint to be enabled/disabled (QModelIndex)
285 @param enabled flag indicating the enabled status to be set (boolean)
286 """
287 sindex = self.__toSourceIndex(index)
288 if sindex.isValid():
289 self.__model.setBreakPointEnabledByIndex(sindex, enabled)
290
291 def __enableBreak(self):
292 """
293 Private slot to handle the enable breakpoint context menu entry.
294 """
295 index = self.currentIndex()
296 self.__setBpEnabled(index, True)
297 self.__resizeColumns()
298 self.__resort()
299
300 def __enableAllBreaks(self):
301 """
302 Private slot to handle the enable all breakpoints context menu entry.
303 """
304 index = self.model().index(0, 0)
305 while index.isValid():
306 self.__setBpEnabled(index, True)
307 index = self.indexBelow(index)
308 self.__resizeColumns()
309 self.__resort()
310
311 def __enableSelectedBreaks(self):
312 """
313 Private slot to handle the enable selected breakpoints context menu entry.
314 """
315 for index in self.selectedIndexes():
316 if index.column() == 0:
317 self.__setBpEnabled(index, True)
318 self.__resizeColumns()
319 self.__resort()
320
321 def __disableBreak(self):
322 """
323 Private slot to handle the disable breakpoint context menu entry.
324 """
325 index = self.currentIndex()
326 self.__setBpEnabled(index, False)
327 self.__resizeColumns()
328 self.__resort()
329
330 def __disableAllBreaks(self):
331 """
332 Private slot to handle the disable all breakpoints context menu entry.
333 """
334 index = self.model().index(0, 0)
335 while index.isValid():
336 self.__setBpEnabled(index, False)
337 index = self.indexBelow(index)
338 self.__resizeColumns()
339 self.__resort()
340
341 def __disableSelectedBreaks(self):
342 """
343 Private slot to handle the disable selected breakpoints context menu entry.
344 """
345 for index in self.selectedIndexes():
346 if index.column() == 0:
347 self.__setBpEnabled(index, False)
348 self.__resizeColumns()
349 self.__resort()
350
351 def __deleteBreak(self):
352 """
353 Private slot to handle the delete breakpoint context menu entry.
354 """
355 index = self.currentIndex()
356 sindex = self.__toSourceIndex(index)
357 if sindex.isValid():
358 self.__model.deleteBreakPointByIndex(sindex)
359
360 def __deleteAllBreaks(self):
361 """
362 Private slot to handle the delete all breakpoints context menu entry.
363 """
364 self.__model.deleteAll()
365
366 def __deleteSelectedBreaks(self):
367 """
368 Private slot to handle the delete selected breakpoints context menu entry.
369 """
370 idxList = []
371 for index in self.selectedIndexes():
372 sindex = self.__toSourceIndex(index)
373 if sindex.isValid() and index.column() == 0:
374 idxList.append(sindex)
375 self.__model.deleteBreakPoints(idxList)
376
377 def __showSource(self):
378 """
379 Private slot to handle the goto context menu entry.
380 """
381 index = self.currentIndex()
382 sindex = self.__toSourceIndex(index)
383 bp = self.__model.getBreakPointByIndex(sindex)
384 if not bp:
385 return
386
387 fn, line = bp[:2]
388 self.emit(SIGNAL("sourceFile"), fn, line)
389
390 def highlightBreakpoint(self, fn, lineno):
391 """
392 Public slot to handle the clientLine signal.
393
394 @param fn filename of the breakpoint (string)
395 @param lineno line number of the breakpoint (integer)
396 """
397 sindex = self.__model.getBreakPointIndex(fn, lineno)
398 if sindex.isValid():
399 return
400
401 index = self.__fromSourceIndex(sindex)
402 if index.isValid():
403 self.__clearSelection()
404 self.__setRowSelected(index, True)
405
406 def handleResetUI(self):
407 """
408 Public slot to reset the breakpoint viewer.
409 """
410 self.__clearSelection()
411
412 def __showBackMenu(self):
413 """
414 Private slot to handle the aboutToShow signal of the background menu.
415 """
416 if self.model().rowCount() == 0:
417 self.backMenuActions["EnableAll"].setEnabled(False)
418 self.backMenuActions["DisableAll"].setEnabled(False)
419 self.backMenuActions["DeleteAll"].setEnabled(False)
420 else:
421 self.backMenuActions["EnableAll"].setEnabled(True)
422 self.backMenuActions["DisableAll"].setEnabled(True)
423 self.backMenuActions["DeleteAll"].setEnabled(True)
424
425 def __getSelectedItemsCount(self):
426 """
427 Private method to get the count of items selected.
428
429 @return count of items selected (integer)
430 """
431 count = len(self.selectedIndexes()) / (self.__model.columnCount() - 1)
432 # column count is 1 greater than selectable
433 return count
434
435 def __configure(self):
436 """
437 Private method to open the configuration dialog.
438 """
439 e4App().getObject("UserInterface").showPreferences("debuggerGeneralPage")

eric ide

mercurial