|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2002 - 2009 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the variables viewer widget. |
|
8 """ |
|
9 |
|
10 import types |
|
11 from math import log10 |
|
12 import sys |
|
13 |
|
14 from PyQt4.QtCore import * |
|
15 from PyQt4.QtGui import * |
|
16 |
|
17 from E4Gui.E4Application import e4App |
|
18 |
|
19 from Config import ConfigVarTypeDispStrings, ConfigVarTypeStrings |
|
20 from VariableDetailDialog import VariableDetailDialog |
|
21 from Utilities import toUnicode |
|
22 |
|
23 import Preferences |
|
24 |
|
25 |
|
26 class VariableItem(QTreeWidgetItem): |
|
27 """ |
|
28 Class implementing the data structure for variable items. |
|
29 """ |
|
30 def __init__(self, parent, dvar, dvalue, dtype): |
|
31 """ |
|
32 Constructor. |
|
33 |
|
34 @param parent reference to the parent item |
|
35 @param dvar variable name (string) |
|
36 @param dvalue value string (string) |
|
37 @param dtype type string (string) |
|
38 """ |
|
39 self.value = dvalue |
|
40 if len(dvalue) > 2048: # 1024 * 2 |
|
41 dvalue = QApplication.translate("VariableItem", |
|
42 "<double click to show value>") |
|
43 |
|
44 QTreeWidgetItem.__init__(self, parent, [dvar, dvalue, dtype]) |
|
45 |
|
46 self.populated = True |
|
47 |
|
48 def getValue(self): |
|
49 """ |
|
50 Public method to return the value of the item. |
|
51 |
|
52 @return value of the item (string) |
|
53 """ |
|
54 return self.value |
|
55 |
|
56 def data(self, column, role): |
|
57 """ |
|
58 Public method to return the data for the requested role. |
|
59 |
|
60 This implementation changes the original behavior in a way, that the display |
|
61 data is returned as the tooltip for column 1. |
|
62 |
|
63 @param column column number (integer) |
|
64 @param role data role (Qt.ItemDataRole) |
|
65 @return requested data (QVariant) |
|
66 """ |
|
67 if column == 1 and role == Qt.ToolTipRole: |
|
68 role = Qt.DisplayRole |
|
69 return QTreeWidgetItem.data(self, column, role) |
|
70 |
|
71 def attachDummy(self): |
|
72 """ |
|
73 Public method to attach a dummy sub item to allow for lazy population. |
|
74 """ |
|
75 QTreeWidgetItem(self, ["DUMMY"]) |
|
76 |
|
77 def deleteChildren(self): |
|
78 """ |
|
79 Public method to delete all children (cleaning the subtree). |
|
80 """ |
|
81 for itm in self.takeChildren(): |
|
82 del itm |
|
83 |
|
84 def key(self, column): |
|
85 """ |
|
86 Public method generating the key for this item. |
|
87 |
|
88 @param column the column to sort on (integer) |
|
89 @return text of the column (string) |
|
90 """ |
|
91 return self.text(column) |
|
92 |
|
93 def __lt__(self, other): |
|
94 """ |
|
95 Public method to check, if the item is less than the other one. |
|
96 |
|
97 @param other reference to item to compare against (QTreeWidgetItem) |
|
98 @return true, if this item is less than other (boolean) |
|
99 """ |
|
100 column = self.treeWidget().sortColumn() |
|
101 return self.key(column) < other.key(column) |
|
102 |
|
103 def expand(self): |
|
104 """ |
|
105 Public method to expand the item. |
|
106 |
|
107 Note: This is just a do nothing and should be overwritten. |
|
108 """ |
|
109 return |
|
110 |
|
111 def collapse(self): |
|
112 """ |
|
113 Public method to collapse the item. |
|
114 |
|
115 Note: This is just a do nothing and should be overwritten. |
|
116 """ |
|
117 return |
|
118 |
|
119 class SpecialVarItem(VariableItem): |
|
120 """ |
|
121 Class implementing a VariableItem that represents a special variable node. |
|
122 |
|
123 These special variable nodes are generated for classes, lists, |
|
124 tuples and dictionaries. |
|
125 """ |
|
126 def __init__(self, parent, dvar, dvalue, dtype, frmnr, scope): |
|
127 """ |
|
128 Constructor |
|
129 |
|
130 @param parent parent of this item |
|
131 @param dvar variable name (string) |
|
132 @param dvalue value string (string) |
|
133 @param dtype type string (string) |
|
134 @param frmnr frame number (0 is the current frame) (int) |
|
135 @param scope flag indicating global (1) or local (0) variables |
|
136 """ |
|
137 VariableItem.__init__(self, parent, dvar, dvalue, dtype) |
|
138 self.attachDummy() |
|
139 self.populated = False |
|
140 |
|
141 self.framenr = frmnr |
|
142 self.scope = scope |
|
143 |
|
144 def expand(self): |
|
145 """ |
|
146 Public method to expand the item. |
|
147 """ |
|
148 self.deleteChildren() |
|
149 self.populated = True |
|
150 |
|
151 pathlist = [self.text(0)] |
|
152 par = self.parent() |
|
153 |
|
154 # step 1: get a pathlist up to the requested variable |
|
155 while par is not None: |
|
156 pathlist.insert(0, par.text(0)) |
|
157 par = par.parent() |
|
158 |
|
159 # step 2: request the variable from the debugger |
|
160 filter = e4App().getObject("DebugUI").variablesFilter(self.scope) |
|
161 e4App().getObject("DebugServer").remoteClientVariable(\ |
|
162 self.scope, filter, pathlist, self.framenr) |
|
163 |
|
164 class ArrayElementVarItem(VariableItem): |
|
165 """ |
|
166 Class implementing a VariableItem that represents an array element. |
|
167 """ |
|
168 def __init__(self, parent, dvar, dvalue, dtype): |
|
169 """ |
|
170 Constructor |
|
171 |
|
172 @param parent parent of this item |
|
173 @param dvar variable name (string) |
|
174 @param dvalue value string (string) |
|
175 @param dtype type string (string) |
|
176 """ |
|
177 VariableItem.__init__(self, parent, dvar, dvalue, dtype) |
|
178 |
|
179 """ |
|
180 Array elements have numbers as names, but the key must be |
|
181 right justified and zero filled to 6 decimal places. Then |
|
182 element 2 will have a key of '000002' and appear before |
|
183 element 10 with a key of '000010' |
|
184 """ |
|
185 keyStr = self.text(0) |
|
186 self.arrayElementKey = "%.6d" % int(keyStr) |
|
187 |
|
188 def key(self, column): |
|
189 """ |
|
190 Public method generating the key for this item. |
|
191 |
|
192 @param column the column to sort on (integer) |
|
193 """ |
|
194 if column == 0: |
|
195 return self.arrayElementKey |
|
196 else: |
|
197 return VariableItem.key(self, column) |
|
198 |
|
199 class SpecialArrayElementVarItem(SpecialVarItem): |
|
200 """ |
|
201 Class implementing a QTreeWidgetItem that represents a special array variable node. |
|
202 """ |
|
203 def __init__(self, parent, dvar, dvalue, dtype, frmnr, scope): |
|
204 """ |
|
205 Constructor |
|
206 |
|
207 @param parent parent of this item |
|
208 @param dvar variable name (string) |
|
209 @param dvalue value string (string) |
|
210 @param dtype type string (string) |
|
211 @param frmnr frame number (0 is the current frame) (int) |
|
212 @param scope flag indicating global (1) or local (0) variables |
|
213 """ |
|
214 SpecialVarItem.__init__(self, parent, dvar, dvalue, dtype, frmnr, scope) |
|
215 |
|
216 """ |
|
217 Array elements have numbers as names, but the key must be |
|
218 right justified and zero filled to 6 decimal places. Then |
|
219 element 2 will have a key of '000002' and appear before |
|
220 element 10 with a key of '000010' |
|
221 """ |
|
222 keyStr = self.text(0)[:-2] # strip off [], () or {} |
|
223 self.arrayElementKey = "%.6d" % int(keyStr) |
|
224 |
|
225 def key(self, column): |
|
226 """ |
|
227 Public method generating the key for this item. |
|
228 |
|
229 @param column the column to sort on (integer) |
|
230 """ |
|
231 if column == 0: |
|
232 return self.arrayElementKey |
|
233 else: |
|
234 return SpecialVarItem.key(self, column) |
|
235 |
|
236 class VariablesViewer(QTreeWidget): |
|
237 """ |
|
238 Class implementing the variables viewer widget. |
|
239 |
|
240 This widget is used to display the variables of the program being |
|
241 debugged in a tree. Compound types will be shown with |
|
242 their main entry first. Once the subtree has been expanded, the |
|
243 individual entries will be shown. Double clicking an entry will |
|
244 popup a dialog showing the variables parameters in a more readable |
|
245 form. This is especially useful for lengthy strings. |
|
246 |
|
247 This widget has two modes for displaying the global and the local |
|
248 variables. |
|
249 """ |
|
250 def __init__(self, parent=None, scope=1): |
|
251 """ |
|
252 Constructor |
|
253 |
|
254 @param parent the parent (QWidget) |
|
255 @param scope flag indicating global (1) or local (0) variables |
|
256 """ |
|
257 QTreeWidget.__init__(self, parent) |
|
258 |
|
259 self.indicators = {'list' : '[]', 'tuple' : '()', 'dict' : '{}', # Python types |
|
260 'Array' : '[]', 'Hash' : '{}'} # Ruby types |
|
261 |
|
262 self.rx_class = QRegExp('<.*(instance|object) at 0x.*>') |
|
263 self.rx_class2 = QRegExp('class .*') |
|
264 self.rx_class3 = QRegExp('<class .* at 0x.*>') |
|
265 self.dvar_rx_class1 = QRegExp(r'<.*(instance|object) at 0x.*>(\[\]|\{\}|\(\))') |
|
266 self.dvar_rx_class2 = QRegExp(r'<class .* at 0x.*>(\[\]|\{\}|\(\))') |
|
267 self.dvar_rx_array_element = QRegExp(r'^\d+$') |
|
268 self.dvar_rx_special_array_element = QRegExp(r'^\d+(\[\]|\{\}|\(\))$') |
|
269 self.rx_nonprintable = QRegExp(r"""(\\x\d\d)+""") |
|
270 |
|
271 self.framenr = 0 |
|
272 |
|
273 self.loc = Preferences.getSystem("StringEncoding") |
|
274 |
|
275 self.openItems = [] |
|
276 |
|
277 self.setRootIsDecorated(True) |
|
278 self.setAlternatingRowColors(True) |
|
279 self.setSelectionBehavior(QAbstractItemView.SelectRows) |
|
280 |
|
281 self.scope = scope |
|
282 if scope: |
|
283 self.setWindowTitle(self.trUtf8("Global Variables")) |
|
284 self.setHeaderLabels([ |
|
285 self.trUtf8("Globals"), |
|
286 self.trUtf8("Value"), |
|
287 self.trUtf8("Type")]) |
|
288 self.setWhatsThis(self.trUtf8( |
|
289 """<b>The Global Variables Viewer Window</b>""" |
|
290 """<p>This window displays the global variables""" |
|
291 """ of the debugged program.</p>""" |
|
292 )) |
|
293 else: |
|
294 self.setWindowTitle(self.trUtf8("Local Variables")) |
|
295 self.setHeaderLabels([ |
|
296 self.trUtf8("Locals"), |
|
297 self.trUtf8("Value"), |
|
298 self.trUtf8("Type")]) |
|
299 self.setWhatsThis(self.trUtf8( |
|
300 """<b>The Local Variables Viewer Window</b>""" |
|
301 """<p>This window displays the local variables""" |
|
302 """ of the debugged program.</p>""" |
|
303 )) |
|
304 |
|
305 header = self.header() |
|
306 header.setSortIndicator(0, Qt.AscendingOrder) |
|
307 header.setSortIndicatorShown(True) |
|
308 header.setClickable(True) |
|
309 header.resizeSection(0, 120) # variable column |
|
310 header.resizeSection(1, 150) # value column |
|
311 |
|
312 self.__createPopupMenus() |
|
313 self.setContextMenuPolicy(Qt.CustomContextMenu) |
|
314 self.connect(self,SIGNAL('customContextMenuRequested(const QPoint &)'), |
|
315 self.__showContextMenu) |
|
316 |
|
317 self.connect(self, SIGNAL("itemExpanded(QTreeWidgetItem *)"), |
|
318 self.__expandItemSignal) |
|
319 self.connect(self, SIGNAL("itemCollapsed(QTreeWidgetItem *)"), |
|
320 self.collapseItem) |
|
321 |
|
322 self.resortEnabled = True |
|
323 |
|
324 def __createPopupMenus(self): |
|
325 """ |
|
326 Private method to generate the popup menus. |
|
327 """ |
|
328 self.menu = QMenu() |
|
329 self.menu.addAction(self.trUtf8("Show Details..."), self.__showDetails) |
|
330 self.menu.addSeparator() |
|
331 self.menu.addAction(self.trUtf8("Configure..."), self.__configure) |
|
332 |
|
333 self.backMenu = QMenu() |
|
334 self.backMenu.addAction(self.trUtf8("Configure..."), self.__configure) |
|
335 |
|
336 def __showContextMenu(self, coord): |
|
337 """ |
|
338 Private slot to show the context menu. |
|
339 |
|
340 @param coord the position of the mouse pointer (QPoint) |
|
341 """ |
|
342 gcoord = self.mapToGlobal(coord) |
|
343 if self.itemAt(coord) is not None: |
|
344 self.menu.popup(gcoord) |
|
345 else: |
|
346 self.backMenu.popup(gcoord) |
|
347 |
|
348 def __findItem(self, slist, column, node=None): |
|
349 """ |
|
350 Private method to search for an item. |
|
351 |
|
352 It is used to find a specific item in column, |
|
353 that is a child of node. If node is None, a child of the |
|
354 QTreeWidget is searched. |
|
355 |
|
356 @param slist searchlist (list of strings) |
|
357 @param column index of column to search in (int) |
|
358 @param node start point of the search |
|
359 @return the found item or None |
|
360 """ |
|
361 if node is None: |
|
362 count = self.topLevelItemCount() |
|
363 else: |
|
364 count = node.childCount() |
|
365 |
|
366 for index in range(count): |
|
367 if node is None: |
|
368 itm = self.topLevelItem(index) |
|
369 else: |
|
370 itm = node.child(index) |
|
371 if itm.text(column) == slist[0]: |
|
372 if len(slist) > 1: |
|
373 itm = self.__findItem(slist[1:], column, itm) |
|
374 return itm |
|
375 |
|
376 return None |
|
377 |
|
378 def showVariables(self, vlist, frmnr): |
|
379 """ |
|
380 Public method to show variables in a list. |
|
381 |
|
382 @param vlist the list of variables to be displayed. Each |
|
383 listentry is a tuple of three values. |
|
384 <ul> |
|
385 <li>the variable name (string)</li> |
|
386 <li>the variables type (string)</li> |
|
387 <li>the variables value (string)</li> |
|
388 </ul> |
|
389 @param frmnr frame number (0 is the current frame) (int) |
|
390 """ |
|
391 self.current = self.currentItem() |
|
392 if self.current: |
|
393 self.curpathlist = self.__buildTreePath(self.current) |
|
394 self.clear() |
|
395 self.__scrollToItem = None |
|
396 self.framenr = frmnr |
|
397 |
|
398 if len(vlist): |
|
399 self.resortEnabled = False |
|
400 for (var, vtype, value) in vlist: |
|
401 self.__addItem(None, vtype, var, value) |
|
402 |
|
403 # reexpand tree |
|
404 openItems = self.openItems[:] |
|
405 openItems.sort() |
|
406 self.openItems = [] |
|
407 for itemPath in openItems: |
|
408 itm = self.__findItem(itemPath, 0) |
|
409 if itm is not None: |
|
410 self.expandItem(itm) |
|
411 else: |
|
412 self.openItems.append(itemPath) |
|
413 |
|
414 if self.current: |
|
415 citm = self.__findItem(self.curpathlist, 0) |
|
416 if citm: |
|
417 self.setCurrentItem(citm) |
|
418 self.setItemSelected(citm, True) |
|
419 self.scrollToItem(citm, QAbstractItemView.PositionAtTop) |
|
420 self.current = None |
|
421 |
|
422 self.resortEnabled = True |
|
423 self.__resort() |
|
424 |
|
425 def showVariable(self, vlist): |
|
426 """ |
|
427 Public method to show variables in a list. |
|
428 |
|
429 @param vlist the list of subitems to be displayed. |
|
430 The first element gives the path of the |
|
431 parent variable. Each other listentry is |
|
432 a tuple of three values. |
|
433 <ul> |
|
434 <li>the variable name (string)</li> |
|
435 <li>the variables type (string)</li> |
|
436 <li>the variables value (string)</li> |
|
437 </ul> |
|
438 """ |
|
439 resortEnabled = self.resortEnabled |
|
440 self.resortEnabled = False |
|
441 if self.current is None: |
|
442 self.current = self.currentItem() |
|
443 if self.current: |
|
444 self.curpathlist = self.__buildTreePath(self.current) |
|
445 |
|
446 subelementsAdded = False |
|
447 if vlist: |
|
448 itm = self.__findItem(vlist[0], 0) |
|
449 for var, vtype, value in vlist[1:]: |
|
450 self.__addItem(itm, vtype, var, value) |
|
451 subelementsAdded = True |
|
452 |
|
453 # reexpand tree |
|
454 openItems = self.openItems[:] |
|
455 openItems.sort() |
|
456 self.openItems = [] |
|
457 for itemPath in openItems: |
|
458 itm = self.__findItem(itemPath, 0) |
|
459 if itm is not None and not itm.isExpanded(): |
|
460 if itm.populated: |
|
461 self.blockSignals(True) |
|
462 itm.setExpanded(True) |
|
463 self.blockSignals(False) |
|
464 else: |
|
465 self.expandItem(itm) |
|
466 self.openItems = openItems[:] |
|
467 |
|
468 if self.current: |
|
469 citm = self.__findItem(self.curpathlist, 0) |
|
470 if citm: |
|
471 self.setCurrentItem(citm) |
|
472 self.setItemSelected(citm, True) |
|
473 if self.__scrollToItem: |
|
474 self.scrollToItem(self.__scrollToItem, |
|
475 QAbstractItemView.PositionAtTop) |
|
476 else: |
|
477 self.scrollToItem(citm, QAbstractItemView.PositionAtTop) |
|
478 self.current = None |
|
479 elif self.__scrollToItem: |
|
480 self.scrollToItem(self.__scrollToItem, QAbstractItemView.PositionAtTop) |
|
481 |
|
482 self.resortEnabled = resortEnabled |
|
483 self.__resort() |
|
484 |
|
485 def __generateItem(self, parent, dvar, dvalue, dtype, isSpecial = False): |
|
486 """ |
|
487 Private method used to generate a VariableItem. |
|
488 |
|
489 @param parent parent of the item to be generated |
|
490 @param dvar variable name (string) |
|
491 @param dvalue value string (string) |
|
492 @param dtype type string (string) |
|
493 @param isSpecial flag indicating that a special node should be generated (boolean) |
|
494 @return The item that was generated (VariableItem). |
|
495 """ |
|
496 if isSpecial and \ |
|
497 (self.dvar_rx_class1.exactMatch(dvar) or \ |
|
498 self.dvar_rx_class2.exactMatch(dvar)): |
|
499 isSpecial = False |
|
500 |
|
501 if self.rx_class2.exactMatch(dtype): |
|
502 return SpecialVarItem(parent, dvar, dvalue, dtype[7:-1], |
|
503 self.framenr, self.scope) |
|
504 elif dtype != "void *" and \ |
|
505 (self.rx_class.exactMatch(dvalue) or \ |
|
506 self.rx_class3.exactMatch(dvalue) or \ |
|
507 isSpecial): |
|
508 if self.dvar_rx_special_array_element.exactMatch(dvar): |
|
509 return SpecialArrayElementVarItem(parent, dvar, dvalue, dtype, |
|
510 self.framenr, self.scope) |
|
511 else: |
|
512 return SpecialVarItem(parent, dvar, dvalue, dtype, |
|
513 self.framenr, self.scope) |
|
514 else: |
|
515 if self.dvar_rx_array_element.exactMatch(dvar): |
|
516 return ArrayElementVarItem(parent, dvar, dvalue, dtype) |
|
517 else: |
|
518 return VariableItem(parent, dvar, dvalue, dtype) |
|
519 |
|
520 def __unicode(self, s): |
|
521 """ |
|
522 Private method to convert a string to unicode. |
|
523 |
|
524 @param s the string to be converted (string) |
|
525 @return unicode representation of s (unicode object) |
|
526 """ |
|
527 if type(s) is type(u""): |
|
528 return s |
|
529 try: |
|
530 u = unicode(s, self.loc) |
|
531 except TypeError: |
|
532 u = str(s) |
|
533 except UnicodeError: |
|
534 u = toUnicode(s) |
|
535 return u |
|
536 |
|
537 def __addItem(self, parent, vtype, var, value): |
|
538 """ |
|
539 Private method used to add an item to the list. |
|
540 |
|
541 If the item is of a type with subelements (i.e. list, dictionary, |
|
542 tuple), these subelements are added by calling this method recursively. |
|
543 |
|
544 @param parent the parent of the item to be added |
|
545 (QTreeWidgetItem or None) |
|
546 @param vtype the type of the item to be added |
|
547 (string) |
|
548 @param var the variable name (string) |
|
549 @param value the value string (string) |
|
550 @return The item that was added to the listview (QTreeWidgetItem). |
|
551 """ |
|
552 if parent is None: |
|
553 parent = self |
|
554 try: |
|
555 dvar = '%s%s' % (var, self.indicators[vtype]) |
|
556 except KeyError: |
|
557 dvar = var |
|
558 dvtype = self.__getDispType(vtype) |
|
559 |
|
560 if vtype in ['list', 'Array', 'tuple', 'dict', 'Hash']: |
|
561 itm = self.__generateItem(parent, dvar, |
|
562 self.trUtf8("{0} items").format(value), |
|
563 dvtype, True) |
|
564 elif vtype in ['unicode', 'str']: |
|
565 if self.rx_nonprintable.indexIn(value) != -1: |
|
566 sval = value |
|
567 else: |
|
568 try: |
|
569 sval = eval(value) |
|
570 except: |
|
571 sval = value |
|
572 itm = self.__generateItem(parent, dvar, self.__unicode(sval), dvtype) |
|
573 |
|
574 else: |
|
575 itm = self.__generateItem(parent, dvar, value, dvtype) |
|
576 |
|
577 return itm |
|
578 |
|
579 def __getDispType(self, vtype): |
|
580 """ |
|
581 Private method used to get the display string for type vtype. |
|
582 |
|
583 @param vtype the type, the display string should be looked up for |
|
584 (string) |
|
585 @return displaystring (string) |
|
586 """ |
|
587 try: |
|
588 i = ConfigVarTypeStrings.index(vtype) |
|
589 dvtype = self.trUtf8(ConfigVarTypeDispStrings[i]) |
|
590 except ValueError: |
|
591 if vtype == 'classobj': |
|
592 dvtype = self.trUtf8(\ |
|
593 ConfigVarTypeDispStrings[ConfigVarTypeStrings.index('instance')]\ |
|
594 ) |
|
595 else: |
|
596 dvtype = vtype |
|
597 return dvtype |
|
598 |
|
599 def mouseDoubleClickEvent(self, mouseEvent): |
|
600 """ |
|
601 Protected method of QAbstractItemView. |
|
602 |
|
603 Reimplemented to disable expanding/collapsing |
|
604 of items when double-clicking. Instead the double-clicked entry is opened. |
|
605 |
|
606 @param mouseEvent the mouse event object (QMouseEvent) |
|
607 """ |
|
608 itm = self.itemAt(mouseEvent.pos()) |
|
609 self.__showVariableDetails(itm) |
|
610 |
|
611 def __showDetails(self): |
|
612 """ |
|
613 Private slot to show details about the selected variable. |
|
614 """ |
|
615 itm = self.currentItem() |
|
616 self.__showVariableDetails(itm) |
|
617 |
|
618 def __showVariableDetails(self, itm): |
|
619 """ |
|
620 Private method to show details about a variable. |
|
621 |
|
622 @param itm reference to the variable item |
|
623 """ |
|
624 if itm is None: |
|
625 return |
|
626 |
|
627 val = itm.getValue() |
|
628 |
|
629 if not val: |
|
630 return # do not display anything, if the variable has no value |
|
631 |
|
632 vtype = itm.text(2) |
|
633 name = itm.text(0) |
|
634 if name[-2:] in ['[]', '{}', '()']: |
|
635 name = name[:-2] |
|
636 |
|
637 par = itm.parent() |
|
638 nlist = [name] |
|
639 # build up the fully qualified name |
|
640 while par is not None: |
|
641 pname = par.text(0) |
|
642 if pname[-2:] in ['[]', '{}', '()']: |
|
643 if nlist[0].endswith("."): |
|
644 nlist[0] = '[%s].' % nlist[0][:-1] |
|
645 else: |
|
646 nlist[0] = '[%s]' % nlist[0] |
|
647 nlist.insert(0, pname[:-2]) |
|
648 else: |
|
649 nlist.insert(0, '%s.' % pname) |
|
650 par = par.parent() |
|
651 |
|
652 name = ''.join(nlist) |
|
653 # now show the dialog |
|
654 dlg = VariableDetailDialog(name, vtype, val) |
|
655 dlg.exec_() |
|
656 |
|
657 def __buildTreePath(self, itm): |
|
658 """ |
|
659 Private method to build up a path from the top to an item. |
|
660 |
|
661 @param itm item to build the path for (QTreeWidgetItem) |
|
662 @return list of names denoting the path from the top (list of strings) |
|
663 """ |
|
664 name = itm.text(0) |
|
665 pathlist = [name] |
|
666 |
|
667 par = itm.parent() |
|
668 # build up a path from the top to the item |
|
669 while par is not None: |
|
670 pname = par.text(0) |
|
671 pathlist.insert(0, pname) |
|
672 par = par.parent() |
|
673 |
|
674 return pathlist[:] |
|
675 |
|
676 def __expandItemSignal(self, parentItem): |
|
677 """ |
|
678 Private slot to handle the expanded signal. |
|
679 |
|
680 @param parentItem reference to the item being expanded (QTreeWidgetItem) |
|
681 """ |
|
682 self.expandItem(parentItem) |
|
683 self.__scrollToItem = parentItem |
|
684 |
|
685 def expandItem(self, parentItem): |
|
686 """ |
|
687 Public slot to handle the expanded signal. |
|
688 |
|
689 @param parentItem reference to the item being expanded (QTreeWidgetItem) |
|
690 """ |
|
691 pathlist = self.__buildTreePath(parentItem) |
|
692 self.openItems.append(pathlist) |
|
693 if parentItem.populated: |
|
694 return |
|
695 |
|
696 try: |
|
697 parentItem.expand() |
|
698 self.__resort() |
|
699 except AttributeError: |
|
700 QTreeWidget.expandItem(self, parentItem) |
|
701 |
|
702 def collapseItem(self, parentItem): |
|
703 """ |
|
704 Public slot to handle the collapsed signal. |
|
705 |
|
706 @param parentItem reference to the item being collapsed (QTreeWidgetItem) |
|
707 """ |
|
708 pathlist = self.__buildTreePath(parentItem) |
|
709 self.openItems.remove(pathlist) |
|
710 |
|
711 try: |
|
712 parentItem.collapse() |
|
713 except AttributeError: |
|
714 QTreeWidget.collapseItem(self, parentItem) |
|
715 |
|
716 def __resort(self): |
|
717 """ |
|
718 Private method to resort the tree. |
|
719 """ |
|
720 if self.resortEnabled: |
|
721 self.sortItems(self.sortColumn(), self.header().sortIndicatorOrder()) |
|
722 |
|
723 def handleResetUI(self): |
|
724 """ |
|
725 Public method to reset the VariablesViewer. |
|
726 """ |
|
727 self.clear() |
|
728 self.openItems = [] |
|
729 |
|
730 def __configure(self): |
|
731 """ |
|
732 Private method to open the configuration dialog. |
|
733 """ |
|
734 e4App().getObject("UserInterface").showPreferences("debuggerGeneralPage") |