Debugger/WatchPointViewer.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 watch expression viewer widget.
8 """
9
10 from PyQt4.QtCore import *
11 from PyQt4.QtGui import *
12
13 from E4Gui.E4Application import e4App
14
15 from EditWatchpointDialog import EditWatchpointDialog
16
17 import Utilities
18
19 class WatchPointViewer(QTreeView):
20 """
21 Class implementing the watch expression viewer widget.
22
23 Watch expressions will be shown with all their details. They can be modified through
24 the context menu of this widget.
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("WatchExpressionViewer")
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("Watchpoints"))
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 def setModel(self, model):
54 """
55 Public slot to set the watch expression model.
56
57 @param reference to the watch expression model (WatchPointModel)
58 """
59 self.__model = model
60
61 self.sortingModel = QSortFilterProxyModel()
62 self.sortingModel.setSourceModel(self.__model)
63 QTreeView.setModel(self, self.sortingModel)
64
65 header = self.header()
66 header.setSortIndicator(0, Qt.AscendingOrder)
67 header.setSortIndicatorShown(True)
68 header.setClickable(True)
69
70 self.setSortingEnabled(True)
71
72 self.__layoutDisplay()
73
74 def __layoutDisplay(self):
75 """
76 Private slot to perform a layout operation.
77 """
78 self.doItemsLayout()
79 self.__resizeColumns()
80 self.__resort()
81
82 def __resizeColumns(self):
83 """
84 Private slot to resize the view when items get added, edited or deleted.
85 """
86 self.header().resizeSections(QHeaderView.ResizeToContents)
87 self.header().setStretchLastSection(True)
88
89 def __resort(self):
90 """
91 Private slot to resort the tree.
92 """
93 self.model().sort(self.header().sortIndicatorSection(),
94 self.header().sortIndicatorOrder())
95
96 def __toSourceIndex(self, index):
97 """
98 Private slot to convert an index to a source index.
99
100 @param index index to be converted (QModelIndex)
101 """
102 return self.sortingModel.mapToSource(index)
103
104 def __fromSourceIndex(self, sindex):
105 """
106 Private slot to convert a source index to an index.
107
108 @param sindex source index to be converted (QModelIndex)
109 """
110 return self.sortingModel.mapFromSource(sindex)
111
112 def __setRowSelected(self, index, selected = True):
113 """
114 Private slot to select a complete row.
115
116 @param index index determining the row to be selected (QModelIndex)
117 @param selected flag indicating the action (bool)
118 """
119 if not index.isValid():
120 return
121
122 if selected:
123 flags = QItemSelectionModel.SelectionFlags(\
124 QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows)
125 else:
126 flags = QItemSelectionModel.SelectionFlags(\
127 QItemSelectionModel.Deselect | QItemSelectionModel.Rows)
128 self.selectionModel().select(index, flags)
129
130 def __createPopupMenus(self):
131 """
132 Private method to generate the popup menus.
133 """
134 self.menu = QMenu()
135 self.menu.addAction(self.trUtf8("Add"), self.__addWatchPoint)
136 self.menu.addAction(self.trUtf8("Edit..."), self.__editWatchPoint)
137 self.menu.addSeparator()
138 self.menu.addAction(self.trUtf8("Enable"), self.__enableWatchPoint)
139 self.menu.addAction(self.trUtf8("Enable all"), self.__enableAllWatchPoints)
140 self.menu.addSeparator()
141 self.menu.addAction(self.trUtf8("Disable"), self.__disableWatchPoint)
142 self.menu.addAction(self.trUtf8("Disable all"), self.__disableAllWatchPoints)
143 self.menu.addSeparator()
144 self.menu.addAction(self.trUtf8("Delete"), self.__deleteWatchPoint)
145 self.menu.addAction(self.trUtf8("Delete all"), self.__deleteAllWatchPoints)
146 self.menu.addSeparator()
147 self.menu.addAction(self.trUtf8("Configure..."), self.__configure)
148
149 self.backMenuActions = {}
150 self.backMenu = QMenu()
151 self.backMenu.addAction(self.trUtf8("Add"), self.__addWatchPoint)
152 self.backMenuActions["EnableAll"] = \
153 self.backMenu.addAction(self.trUtf8("Enable all"),
154 self.__enableAllWatchPoints)
155 self.backMenuActions["DisableAll"] = \
156 self.backMenu.addAction(self.trUtf8("Disable all"),
157 self.__disableAllWatchPoints)
158 self.backMenuActions["DeleteAll"] = \
159 self.backMenu.addAction(self.trUtf8("Delete all"),
160 self.__deleteAllWatchPoints)
161 self.backMenu.addSeparator()
162 self.backMenu.addAction(self.trUtf8("Configure..."), self.__configure)
163 self.connect(self.backMenu, SIGNAL('aboutToShow()'), self.__showBackMenu)
164
165 self.multiMenu = QMenu()
166 self.multiMenu.addAction(self.trUtf8("Add"), self.__addWatchPoint)
167 self.multiMenu.addSeparator()
168 self.multiMenu.addAction(self.trUtf8("Enable selected"),
169 self.__enableSelectedWatchPoints)
170 self.multiMenu.addAction(self.trUtf8("Enable all"), self.__enableAllWatchPoints)
171 self.multiMenu.addSeparator()
172 self.multiMenu.addAction(self.trUtf8("Disable selected"),
173 self.__disableSelectedWatchPoints)
174 self.multiMenu.addAction(self.trUtf8("Disable all"), self.__disableAllWatchPoints)
175 self.multiMenu.addSeparator()
176 self.multiMenu.addAction(self.trUtf8("Delete selected"),
177 self.__deleteSelectedWatchPoints)
178 self.multiMenu.addAction(self.trUtf8("Delete all"), self.__deleteAllWatchPoints)
179 self.multiMenu.addSeparator()
180 self.multiMenu.addAction(self.trUtf8("Configure..."), self.__configure)
181
182 def __showContextMenu(self, coord):
183 """
184 Private slot to show the context menu.
185
186 @param coord the position of the mouse pointer (QPoint)
187 """
188 cnt = self.__getSelectedItemsCount()
189 if cnt <= 1:
190 index = self.indexAt(coord)
191 if index.isValid():
192 cnt = 1
193 self.__setRowSelected(index)
194 coord = self.mapToGlobal(coord)
195 if cnt > 1:
196 self.multiMenu.popup(coord)
197 elif cnt == 1:
198 self.menu.popup(coord)
199 else:
200 self.backMenu.popup(coord)
201
202 def __clearSelection(self):
203 """
204 Private slot to clear the selection.
205 """
206 for index in self.selectedIndexes():
207 self.__setRowSelected(index, False)
208
209 def __findDuplicates(self, cond, special, showMessage = False, index = QModelIndex()):
210 """
211 Private method to check, if an entry already exists.
212
213 @param cond condition to check (string)
214 @param special special condition to check (string)
215 @param showMessage flag indicating a message should be shown,
216 if a duplicate entry is found (boolean)
217 @param index index that should not be considered duplicate (QModelIndex)
218 @return flag indicating a duplicate entry (boolean)
219 """
220 idx = self.__model.getWatchPointIndex(cond, special)
221 duplicate = idx.isValid() and idx.internalPointer() != index.internalPointer()
222 if showMessage and duplicate:
223 if not special:
224 msg = self.trUtf8("""<p>A watch expression '<b>{0}</b>'"""
225 """ already exists.</p>""")\
226 .format(Utilities.html_encode(cond))
227 else:
228 msg = self.trUtf8("""<p>A watch expression '<b>{0}</b>'"""
229 """ for the variable <b>{1}</b> already exists.</p>""")\
230 .format(special, Utilities.html_encode(cond))
231 QMessageBox.warning(None,
232 self.trUtf8("Watch expression already exists"),
233 msg)
234
235 return duplicate
236
237 def __clearSelection(self):
238 """
239 Private slot to clear the selection.
240 """
241 for index in self.selectedIndexes():
242 self.__setRowSelected(index, False)
243
244 def __addWatchPoint(self):
245 """
246 Private slot to handle the add watch expression context menu entry.
247 """
248 dlg = EditWatchpointDialog(("", False, True, 0, ""), self)
249 if dlg.exec_() == QDialog.Accepted:
250 cond, temp, enabled, ignorecount, special = dlg.getData()
251 if not self.__findDuplicates(cond, special, True):
252 self.__model.addWatchPoint(cond, special, (temp, enabled, ignorecount))
253 self.__resizeColumns()
254 self.__resort()
255
256 def __doubleClicked(self, index):
257 """
258 Private slot to handle the double clicked signal.
259
260 @param index index of the entry that was double clicked (QModelIndex)
261 """
262 if index.isValid():
263 self.__doEditWatchPoint(index)
264
265 def __editWatchPoint(self):
266 """
267 Private slot to handle the edit watch expression context menu entry.
268 """
269 index = self.currentIndex()
270 if index.isValid():
271 self.__doEditWatchPoint(index)
272
273 def __doEditWatchPoint(self, index):
274 """
275 Private slot to edit a watch expression.
276
277 @param index index of watch expression to be edited (QModelIndex)
278 """
279 sindex = self.__toSourceIndex(index)
280 if sindex.isValid():
281 wp = self.__model.getWatchPointByIndex(sindex)
282 if not wp:
283 return
284
285 cond, special, temp, enabled, count = wp[:5]
286
287 dlg = EditWatchpointDialog(\
288 (cond, temp, enabled, count, special), self)
289 if dlg.exec_() == QDialog.Accepted:
290 cond, temp, enabled, count, special = dlg.getData()
291 if not self.__findDuplicates(cond, special, True, index):
292 self.__model.setWatchPointByIndex(sindex,
293 cond, special, (temp, enabled, count))
294 self.__resizeColumns()
295 self.__resort()
296
297 def __setWpEnabled(self, index, enabled):
298 """
299 Private method to set the enabled status of a watch expression.
300
301 @param index index of watch expression to be enabled/disabled (QModelIndex)
302 @param enabled flag indicating the enabled status to be set (boolean)
303 """
304 sindex = self.__toSourceIndex(index)
305 if sindex.isValid():
306 self.__model.setWatchPointEnabledByIndex(sindex, enabled)
307
308 def __enableWatchPoint(self):
309 """
310 Private slot to handle the enable watch expression context menu entry.
311 """
312 index = self.currentIndex()
313 self.__setWpEnabled(index, True)
314 self.__resizeColumns()
315 self.__resort()
316
317 def __enableAllWatchPoints(self):
318 """
319 Private slot to handle the enable all watch expressions context menu entry.
320 """
321 index = self.model().index(0, 0)
322 while index.isValid():
323 self.__setWpEnabled(index, True)
324 index = self.indexBelow(index)
325 self.__resizeColumns()
326 self.__resort()
327
328 def __enableSelectedWatchPoints(self):
329 """
330 Private slot to handle the enable selected watch expressions context menu entry.
331 """
332 for index in self.selectedIndexes():
333 if index.column() == 0:
334 self.__setWpEnabled(index, True)
335 self.__resizeColumns()
336 self.__resort()
337
338 def __disableWatchPoint(self):
339 """
340 Private slot to handle the disable watch expression context menu entry.
341 """
342 index = self.currentIndex()
343 self.__setWpEnabled(index, False)
344 self.__resizeColumns()
345 self.__resort()
346
347 def __disableAllWatchPoints(self):
348 """
349 Private slot to handle the disable all watch expressions context menu entry.
350 """
351 index = self.model().index(0, 0)
352 while index.isValid():
353 self.__setWpEnabled(index, False)
354 index = self.indexBelow(index)
355 self.__resizeColumns()
356 self.__resort()
357
358 def __disableSelectedWatchPoints(self):
359 """
360 Private slot to handle the disable selected watch expressions context menu entry.
361 """
362 for index in self.selectedIndexes():
363 if index.column() == 0:
364 self.__setWpEnabled(index, False)
365 self.__resizeColumns()
366 self.__resort()
367
368 def __deleteWatchPoint(self):
369 """
370 Private slot to handle the delete watch expression context menu entry.
371 """
372 index = self.currentIndex()
373 sindex = self.__toSourceIndex(index)
374 if sindex.isValid():
375 self.__model.deleteWatchPointByIndex(sindex)
376
377 def __deleteAllWatchPoints(self):
378 """
379 Private slot to handle the delete all watch expressions context menu entry.
380 """
381 self.__model.deleteAll()
382
383 def __deleteSelectedWatchPoints(self):
384 """
385 Private slot to handle the delete selected watch expressions context menu entry.
386 """
387 idxList = []
388 for index in self.selectedIndexes():
389 sindex = self.__toSourceIndex(index)
390 if sindex.isValid() and index.column() == 0:
391 lastrow = index.row()
392 idxList.append(sindex)
393 self.__model.deleteWatchPoints(idxList)
394
395 def __showBackMenu(self):
396 """
397 Private slot to handle the aboutToShow signal of the background menu.
398 """
399 if self.model().rowCount() == 0:
400 self.backMenuActions["EnableAll"].setEnabled(False)
401 self.backMenuActions["DisableAll"].setEnabled(False)
402 self.backMenuActions["DeleteAll"].setEnabled(False)
403 else:
404 self.backMenuActions["EnableAll"].setEnabled(True)
405 self.backMenuActions["DisableAll"].setEnabled(True)
406 self.backMenuActions["DeleteAll"].setEnabled(True)
407
408 def __getSelectedItemsCount(self):
409 """
410 Private method to get the count of items selected.
411
412 @return count of items selected (integer)
413 """
414 count = len(self.selectedIndexes()) / (self.__model.columnCount()-1)
415 # column count is 1 greater than selectable
416 return count
417
418 def __configure(self):
419 """
420 Private method to open the configuration dialog.
421 """
422 e4App().getObject("UserInterface").showPreferences("debuggerGeneralPage")

eric ide

mercurial