eric6/UI/PythonDisViewer.py

changeset 7710
9aad21c7765d
parent 7707
6abcf4275d0e
child 7711
5e6792b85a8a
equal deleted inserted replaced
7709:7c3968742fd2 7710:9aad21c7765d
15 15
16 16
17 from PyQt5.QtCore import pyqtSlot, Qt, QTimer 17 from PyQt5.QtCore import pyqtSlot, Qt, QTimer
18 from PyQt5.QtGui import QCursor, QBrush 18 from PyQt5.QtGui import QCursor, QBrush
19 from PyQt5.QtWidgets import ( 19 from PyQt5.QtWidgets import (
20 QTreeWidget, QApplication, QTreeWidgetItem, QAbstractItemView, QWidget, 20 QApplication, QTreeWidgetItem, QAbstractItemView, QWidget, QMenu
21 QVBoxLayout, QLabel, QMenu
22 ) 21 )
23 22
24 import Preferences 23 import Preferences
24
25 from .Ui_PythonDisViewer import Ui_PythonDisViewer
25 26
26 27
27 class PythonDisViewerModes(enum.Enum): 28 class PythonDisViewerModes(enum.Enum):
28 """ 29 """
29 Class implementing the disassembly viewer operation modes. 30 Class implementing the disassembly viewer operation modes.
30 """ 31 """
31 SourceDisassemblyMode = 0 32 SourceDisassemblyMode = 0
32 TracebackMode = 1 33 TracebackMode = 1
33 34
34 35
35 class PythonDisViewer(QWidget): 36 class PythonDisViewer(QWidget, Ui_PythonDisViewer):
36 """ 37 """
37 Class implementing a widget to visualize the Python Disassembly for some 38 Class implementing a widget to visualize the Python Disassembly for some
38 Python sources. 39 Python sources.
39 """ 40 """
40 StartLineRole = Qt.UserRole 41 StartLineRole = Qt.UserRole
41 EndLineRole = Qt.UserRole + 1 42 EndLineRole = Qt.UserRole + 1
43 CodeInfoRole = Qt.UserRole + 2
42 44
43 def __init__(self, viewmanager, 45 def __init__(self, viewmanager,
44 mode=PythonDisViewerModes.SourceDisassemblyMode, 46 mode=PythonDisViewerModes.SourceDisassemblyMode,
45 parent=None): 47 parent=None):
46 """ 48 """
52 @type int 54 @type int
53 @param parent reference to the parent widget 55 @param parent reference to the parent widget
54 @type QWidget 56 @type QWidget
55 """ 57 """
56 super(PythonDisViewer, self).__init__(parent) 58 super(PythonDisViewer, self).__init__(parent)
57 59 self.setupUi(self)
58 self.__layout = QVBoxLayout(self)
59 self.setLayout(self.__layout)
60 self.__disWidget = QTreeWidget(self)
61 self.__layout.addWidget(self.__disWidget)
62 self.__layout.setContentsMargins(0, 0, 0, 0)
63
64 self.__currentInfoLabel = QLabel(self.tr(
65 "italic: current instruction"))
66 self.__labeledInfoLabel = QLabel(self.tr(
67 "bold: labeled instruction"))
68 self.__layout.addWidget(self.__currentInfoLabel)
69 self.__layout.addWidget(self.__labeledInfoLabel)
70 60
71 self.setWindowTitle(self.tr("Disassembly")) 61 self.setWindowTitle(self.tr("Disassembly"))
72 62
73 self.__vm = viewmanager 63 self.__vm = viewmanager
74 self.__vmConnected = False 64 self.__vmConnected = False
76 self.__mode = mode 66 self.__mode = mode
77 67
78 self.__editor = None 68 self.__editor = None
79 self.__source = "" 69 self.__source = ""
80 70
81 self.__disWidget.setHeaderLabels( 71 self.disWidget.setHeaderLabels(
82 [self.tr("Line"), self.tr("Offset"), self.tr("Operation"), 72 [self.tr("Line"), self.tr("Offset"), self.tr("Operation"),
83 self.tr("Parameters"), self.tr("Interpreted Parameters")]) 73 self.tr("Parameters"), self.tr("Interpreted Parameters")])
84 self.__disWidget.setSortingEnabled(False) 74 self.codeInfoWidget.setHeaderLabels(
85 self.__disWidget.setSelectionBehavior(QAbstractItemView.SelectRows) 75 [self.tr("Key"), self.tr("Value")])
86 self.__disWidget.setSelectionMode(QAbstractItemView.SingleSelection) 76
87 self.__disWidget.setAlternatingRowColors(True) 77 self.__disMenu = QMenu(self.disWidget)
88 78 if self.__mode == PythonDisViewerModes.SourceDisassemblyMode:
89 self.__menu = QMenu(self.__disWidget) 79 self.__codeInfoAct = self.__disMenu.addAction(
90 self.__menu.addAction(self.tr('Expand All'), self.__expandAll) 80 self.tr("Show Code Info"), self.__showCodeInfo)
91 self.__menu.addAction(self.tr('Collapse All'), self.__collapseAll) 81 self.__disMenu.addSeparator()
92 82 self.__disMenu.addAction(
93 self.__disWidget.setContextMenuPolicy(Qt.CustomContextMenu) 83 self.tr('Expand All'), self.__expandAllDis)
94 self.__disWidget.customContextMenuRequested.connect( 84 self.__disMenu.addAction(
95 self.__contextMenuRequested) 85 self.tr('Collapse All'), self.__collapseAllDis)
86
87 self.__codeInfoMenu = QMenu(self.codeInfoWidget)
88 if self.__mode == PythonDisViewerModes.SourceDisassemblyMode:
89 self.__codeInfoMenu.addAction(
90 self.tr("Hide"), self.codeInfoWidget.hide)
91 self.__codeInfoMenu.addAction(
92 self.tr('Expand All'), self.__expandAllCodeInfo)
93 self.__codeInfoMenu.addAction(
94 self.tr('Collapse All'), self.__collapseAllCodeInfo)
96 95
97 self.__errorColor = QBrush( 96 self.__errorColor = QBrush(
98 Preferences.getPython("DisViewerErrorColor")) 97 Preferences.getPython("DisViewerErrorColor"))
99 self.__currentInstructionColor = QBrush( 98 self.__currentInstructionColor = QBrush(
100 Preferences.getPython("DisViewerCurrentColor")) 99 Preferences.getPython("DisViewerCurrentColor"))
101 self.__jumpTargetColor = QBrush( 100 self.__jumpTargetColor = QBrush(
102 Preferences.getPython("DisViewerLabeledColor")) 101 Preferences.getPython("DisViewerLabeledColor"))
103 102
104 self.__disWidget.itemClicked.connect(self.__disItemClicked) 103 self.disWidget.itemClicked.connect(self.__disItemClicked)
105 self.__disWidget.itemCollapsed.connect(self.__resizeColumns) 104 self.disWidget.itemCollapsed.connect(self.__resizeDisColumns)
106 self.__disWidget.itemExpanded.connect(self.__resizeColumns) 105 self.disWidget.itemExpanded.connect(self.__resizeDisColumns)
106 self.disWidget.customContextMenuRequested.connect(
107 self.__disContextMenuRequested)
108
109 self.codeInfoWidget.itemCollapsed.connect(self.__resizeCodeInfoColumns)
110 self.codeInfoWidget.itemExpanded.connect(self.__resizeCodeInfoColumns)
111 self.codeInfoWidget.customContextMenuRequested.connect(
112 self.__codeInfoContextMenuRequested)
107 113
108 if self.__mode == PythonDisViewerModes.SourceDisassemblyMode: 114 if self.__mode == PythonDisViewerModes.SourceDisassemblyMode:
109 self.__vm.disViewerStateChanged.connect( 115 self.__vm.disViewerStateChanged.connect(
110 self.__disViewerStateChanged) 116 self.__disViewerStateChanged)
117
118 self.codeInfoWidget.hide()
111 119
112 self.hide() 120 self.hide()
121
113 elif self.__mode == PythonDisViewerModes.TracebackMode: 122 elif self.__mode == PythonDisViewerModes.TracebackMode:
114 self.__styleLabels() 123 self.__styleLabels()
115 124
116 def __contextMenuRequested(self, coord): 125 def __disContextMenuRequested(self, coord):
117 """ 126 """
118 Private slot to show the context menu. 127 Private slot to show the context menu of the disassembly widget.
119 128
120 @param coord position of the mouse pointer 129 @param coord position of the mouse pointer
121 @type QPoint 130 @type QPoint
122 """ 131 """
123 coord = self.__disWidget.mapToGlobal(coord) 132 if self.__mode == PythonDisViewerModes.SourceDisassemblyMode:
124 self.__menu.popup(coord) 133 itm = self.disWidget.itemAt(coord)
134 self.__codeInfoAct.setEnabled(bool(itm.data(0, self.CodeInfoRole)))
135 self.disWidget.setCurrentItem(itm)
136
137 if self.disWidget.topLevelItemCount() > 0:
138 # don't show context menu on empty list
139 coord = self.disWidget.mapToGlobal(coord)
140 self.__disMenu.popup(coord)
125 141
126 def __editorChanged(self, editor): 142 def __editorChanged(self, editor):
127 """ 143 """
128 Private slot to handle a change of the current editor. 144 Private slot to handle a change of the current editor.
129 145
243 self.__loadDIS() 259 self.__loadDIS()
244 else: 260 else:
245 self.hide() 261 self.hide()
246 self.__editor = None 262 self.__editor = None
247 263
248 def __expandAll(self): 264 def __expandAllDis(self):
249 """ 265 """
250 Private slot to expand all items. 266 Private slot to expand all items of the disassembly widget.
251 """ 267 """
252 block = self.__disWidget.blockSignals(True) 268 block = self.disWidget.blockSignals(True)
253 self.__disWidget.expandAll() 269 self.disWidget.expandAll()
254 self.__disWidget.blockSignals(block) 270 self.disWidget.blockSignals(block)
255 self.__resizeColumns() 271 self.__resizeDisColumns()
256 272
257 def __collapseAll(self): 273 def __collapseAllDis(self):
258 """ 274 """
259 Private slot to collapse all items. 275 Private slot to collapse all items of the disassembly widget.
260 """ 276 """
261 block = self.__disWidget.blockSignals(True) 277 block = self.disWidget.blockSignals(True)
262 self.__disWidget.collapseAll() 278 self.disWidget.collapseAll()
263 self.__disWidget.blockSignals(block) 279 self.disWidget.blockSignals(block)
264 self.__resizeColumns() 280 self.__resizeDisColumns()
265 281
266 def __createErrorItem(self, error): 282 def __createErrorItem(self, error):
267 """ 283 """
268 Private method to create a top level error item. 284 Private method to create a top level error item.
269 285
270 @param error error message 286 @param error error message
271 @type str 287 @type str
272 @return generated item 288 @return generated item
273 @rtype QTreeWidgetItem 289 @rtype QTreeWidgetItem
274 """ 290 """
275 itm = QTreeWidgetItem(self.__disWidget, [error]) 291 itm = QTreeWidgetItem(self.disWidget, [error])
276 itm.setFirstColumnSpanned(True) 292 itm.setFirstColumnSpanned(True)
277 itm.setForeground(0, self.__errorColor) 293 itm.setForeground(0, self.__errorColor)
278 return itm 294 return itm
279 295
280 def __createTitleItem(self, title, line, parentItem): 296 def __createTitleItem(self, title, line, parentItem):
378 ) 394 )
379 else: 395 else:
380 endLine = itm.data(0, self.StartLineRole) 396 endLine = itm.data(0, self.StartLineRole)
381 itm.setData(0, self.EndLineRole, endLine) 397 itm.setData(0, self.EndLineRole, endLine)
382 398
399 def __createCodeInfo(self, co):
400 """
401 Private method to create a dictionary containing the code info data.
402
403 @param co reference to the code object to generate the info for
404 @type code
405 @return dictionary containing the code info data
406 @rtype dict
407 """
408 return {
409 "name": co.co_name,
410 "filename": co.co_filename,
411 "argcount": co.co_argcount,
412 "posonlyargcount": co.co_posonlyargcount,
413 "kwonlyargcount": co.co_kwonlyargcount,
414 "nlocals": co.co_nlocals,
415 "stacksize": co.co_stacksize,
416 "flags": dis.pretty_flags(co.co_flags),
417 "consts": co.co_consts,
418 "names": co.co_names,
419 "varnames": co.co_varnames,
420 "freevars": co.co_freevars,
421 "cellvars": co.co_cellvars,
422 }
423
383 def __loadDIS(self): 424 def __loadDIS(self):
384 """ 425 """
385 Private method to generate the Disassembly from the source of the 426 Private method to generate the Disassembly from the source of the
386 current editor and visualize it. 427 current editor and visualize it.
387 """ 428 """
393 self.__createErrorItem(self.tr( 434 self.__createErrorItem(self.tr(
394 "No editor has been opened." 435 "No editor has been opened."
395 )) 436 ))
396 return 437 return
397 438
398 self.__disWidget.clear() 439 self.disWidget.clear()
399 self.__editor.clearAllHighlights() 440 self.__editor.clearAllHighlights()
400 441
401 source = self.__editor.text() 442 source = self.__editor.text()
402 if not source.strip(): 443 if not source.strip():
403 # empty editor or white space only 444 # empty editor or white space only
425 codeObject = None 466 codeObject = None
426 self.__createErrorItem(str(exc)) 467 self.__createErrorItem(str(exc))
427 468
428 if codeObject: 469 if codeObject:
429 self.setUpdatesEnabled(False) 470 self.setUpdatesEnabled(False)
430 block = self.__disWidget.blockSignals(True) 471 block = self.disWidget.blockSignals(True)
431 472
432 self.__disassembleObject(codeObject, self.__disWidget, filename) 473 self.__disassembleObject(codeObject, self.disWidget, filename)
433 QTimer.singleShot(0, self.__resizeColumns) 474 QTimer.singleShot(0, self.__resizeDisColumns)
434 475
435 self.__disWidget.blockSignals(block) 476 self.disWidget.blockSignals(block)
436 self.setUpdatesEnabled(True) 477 self.setUpdatesEnabled(True)
437 478
438 QApplication.restoreOverrideCursor() 479 QApplication.restoreOverrideCursor()
439 480
440 @pyqtSlot(dict) 481 @pyqtSlot(dict)
449 if ( 490 if (
450 disassembly and 491 disassembly and
451 "instructions" in disassembly and 492 "instructions" in disassembly and
452 disassembly["instructions"] 493 disassembly["instructions"]
453 ): 494 ):
454 self.__disWidget.clear() 495 self.disWidget.clear()
455 496
456 self.setUpdatesEnabled(False) 497 self.setUpdatesEnabled(False)
457 block = self.__disWidget.blockSignals(True) 498 block = self.disWidget.blockSignals(True)
458 499
459 titleItem = self.__createTitleItem( 500 titleItem = self.__createTitleItem(
460 self.tr("Disassembly of last traceback"), 501 self.tr("Disassembly of last traceback"),
461 disassembly["firstlineno"], 502 disassembly["firstlineno"],
462 self.__disWidget 503 self.disWidget
463 ) 504 )
464 505
465 lasti = disassembly["lasti"] 506 lasti = disassembly["lasti"]
466 lastStartItem = None 507 lastStartItem = None
467 for instrDict in disassembly["instructions"]: 508 for instrDict in disassembly["instructions"]:
484 self.__createInstructionItem( 525 self.__createInstructionItem(
485 instr, lastStartItem, lasti=lasti) 526 instr, lastStartItem, lasti=lasti)
486 if lastStartItem: 527 if lastStartItem:
487 self.__updateItemEndLine(lastStartItem) 528 self.__updateItemEndLine(lastStartItem)
488 529
489 QTimer.singleShot(0, self.__resizeColumns) 530 QTimer.singleShot(0, self.__resizeDisColumns)
490 531
491 self.__disWidget.blockSignals(block) 532 self.disWidget.blockSignals(block)
492 self.setUpdatesEnabled(True) 533 self.setUpdatesEnabled(True)
493 534
494 if lasti: 535 if lasti:
495 lastInstructions = self.__disWidget.findItems( 536 lastInstructions = self.disWidget.findItems(
496 "{0:d}".format(lasti), 537 "{0:d}".format(lasti),
497 Qt.MatchFixedString | Qt.MatchRecursive, 1) 538 Qt.MatchFixedString | Qt.MatchRecursive, 1)
498 if lastInstructions: 539 if lastInstructions:
499 self.__disWidget.scrollToItem( 540 self.disWidget.scrollToItem(
500 lastInstructions[0], 541 lastInstructions[0],
501 QAbstractItemView.PositionAtCenter) 542 QAbstractItemView.PositionAtCenter)
502 543
503 def __resizeColumns(self): 544 if "codeInfo" in disassembly:
504 """ 545 self.__showCodeInfoData(disassembly["codeInfo"])
505 Private method to resize the columns to suitable values. 546
506 """ 547 def __resizeDisColumns(self):
507 for col in range(self.__disWidget.columnCount()): 548 """
508 self.__disWidget.resizeColumnToContents(col) 549 Private method to resize the columns of the disassembly widget to
550 suitable values.
551 """
552 for col in range(self.disWidget.columnCount()):
553 self.disWidget.resizeColumnToContents(col)
509 554
510 def resizeEvent(self, evt): 555 def resizeEvent(self, evt):
511 """ 556 """
512 Protected method to handle resize events. 557 Protected method to handle resize events.
513 558
514 @param evt resize event 559 @param evt resize event
515 @type QResizeEvent 560 @type QResizeEvent
516 """ 561 """
517 # just adjust the sizes of the columns 562 # just adjust the sizes of the columns
518 self.__resizeColumns() 563 self.__resizeDisColumns()
564 self.__resizeCodeInfoColumns()
519 565
520 def __clearSelection(self): 566 def __clearSelection(self):
521 """ 567 """
522 Private method to clear all selected items. 568 Private method to clear all selected items.
523 """ 569 """
524 for itm in self.__disWidget.selectedItems(): 570 for itm in self.disWidget.selectedItems():
525 itm.setSelected(False) 571 itm.setSelected(False)
526 572
527 def __selectChildren(self, itm, lineno): 573 def __selectChildren(self, itm, lineno):
528 """ 574 """
529 Private method to select children of the given item covering the given 575 Private method to select children of the given item covering the given
542 ): 588 ):
543 child.setSelected(True) 589 child.setSelected(True)
544 self.__selectChildren(child, lineno) 590 self.__selectChildren(child, lineno)
545 591
546 if child.data(0, self.StartLineRole) == lineno: 592 if child.data(0, self.StartLineRole) == lineno:
547 self.__disWidget.scrollToItem( 593 self.disWidget.scrollToItem(
548 child, QAbstractItemView.PositionAtCenter) 594 child, QAbstractItemView.PositionAtCenter)
549 595
550 def __selectItemForEditorLine(self): 596 def __selectItemForEditorLine(self):
551 """ 597 """
552 Private slot to select the items corresponding with the cursor line 598 Private slot to select the items corresponding with the cursor line
558 # step 2: retrieve the editor cursor line 604 # step 2: retrieve the editor cursor line
559 cline, cindex = self.__editor.getCursorPosition() 605 cline, cindex = self.__editor.getCursorPosition()
560 # make the line numbers 1-based 606 # make the line numbers 1-based
561 cline += 1 607 cline += 1
562 608
563 for index in range(self.__disWidget.topLevelItemCount()): 609 for index in range(self.disWidget.topLevelItemCount()):
564 itm = self.__disWidget.topLevelItem(index) 610 itm = self.disWidget.topLevelItem(index)
565 if ( 611 if (
566 itm.data(0, self.StartLineRole) <= cline <= 612 itm.data(0, self.StartLineRole) <= cline <=
567 itm.data(0, self.EndLineRole) 613 itm.data(0, self.EndLineRole)
568 ): 614 ):
569 itm.setSelected(True) 615 itm.setSelected(True)
630 else: 676 else:
631 name = co.co_name 677 name = co.co_name
632 title = self.tr("Code Object '{0}'").format(name) 678 title = self.tr("Code Object '{0}'").format(name)
633 titleItem = self.__createTitleItem(title, co.co_firstlineno, 679 titleItem = self.__createTitleItem(title, co.co_firstlineno,
634 parentItem) 680 parentItem)
681 codeInfo = self.__createCodeInfo(co)
682 if codeInfo:
683 titleItem.setData(0, self.CodeInfoRole, codeInfo)
684
635 lastStartItem = None 685 lastStartItem = None
636 for instr in dis.get_instructions(co): 686 for instr in dis.get_instructions(co):
637 if instr.starts_line: 687 if instr.starts_line:
638 if lastStartItem: 688 if lastStartItem:
639 self.__updateItemEndLine(lastStartItem) 689 self.__updateItemEndLine(lastStartItem)
671 def __styleLabels(self): 721 def __styleLabels(self):
672 """ 722 """
673 Private method to style the info labels iaw. selected colors. 723 Private method to style the info labels iaw. selected colors.
674 """ 724 """
675 # current instruction 725 # current instruction
676 self.__currentInfoLabel.setStyleSheet( 726 self.currentInfoLabel.setStyleSheet(
677 "QLabel {{ color : {0}; }}".format( 727 "QLabel {{ color : {0}; }}".format(
678 self.__currentInstructionColor.color().name() 728 self.__currentInstructionColor.color().name()
679 ) 729 )
680 ) 730 )
681 font = self.__currentInfoLabel.font() 731 font = self.currentInfoLabel.font()
682 font.setItalic(True) 732 font.setItalic(True)
683 self.__currentInfoLabel.setFont(font) 733 self.currentInfoLabel.setFont(font)
684 734
685 # labeled instruction 735 # labeled instruction
686 self.__labeledInfoLabel.setStyleSheet( 736 self.labeledInfoLabel.setStyleSheet(
687 "QLabel {{ color : {0}; }}".format( 737 "QLabel {{ color : {0}; }}".format(
688 self.__jumpTargetColor.color().name() 738 self.__jumpTargetColor.color().name()
689 ) 739 )
690 ) 740 )
691 font = self.__labeledInfoLabel.font() 741 font = self.labeledInfoLabel.font()
692 font.setBold(True) 742 font.setBold(True)
693 self.__labeledInfoLabel.setFont(font) 743 self.labeledInfoLabel.setFont(font)
694 744
695 @pyqtSlot() 745 @pyqtSlot()
696 def clear(self): 746 def clear(self):
697 """ 747 """
698 Public method to clear the display. 748 Public method to clear the display.
699 """ 749 """
700 self.__disWidget.clear() 750 self.disWidget.clear()
751
752 def __showCodeInfo(self):
753 """
754 Private slot handling the context menu action to show code info.
755 """
756 itm = self.disWidget.currentItem()
757 codeInfo = itm.data(0, self.CodeInfoRole)
758 if codeInfo:
759 self.codeInfoWidget.show()
760 self.__showCodeInfoData(codeInfo)
761
762 def __showCodeInfoData(self, codeInfo):
763 """
764 Private method to show the passed code info data.
765
766 @param codeInfo dictionary containing the code info data
767 @type dict
768 """
769 def createCodeInfoItems(title, infoList):
770 """
771 Function to create code info items for the given list.
772
773 @param title title string for the list
774 @type str
775 @param infoList list of info strings
776 @type list of str
777 """
778 parent = QTreeWidgetItem(self.codeInfoWidget,
779 [title, str(len(infoList))])
780 # TODO: make this a configuration item
781 parent.setExpanded(False)
782
783 for index, value in enumerate(infoList):
784 itm = QTreeWidgetItem(parent, [str(index), str(value)])
785 itm.setTextAlignment(0, Qt.AlignRight)
786
787 self.codeInfoWidget.clear()
788
789 if codeInfo:
790 QTreeWidgetItem(self.codeInfoWidget, [
791 self.tr("Name"), codeInfo["name"]])
792 QTreeWidgetItem(self.codeInfoWidget, [
793 self.tr("Filename"), codeInfo["filename"]])
794 QTreeWidgetItem(self.codeInfoWidget, [
795 self.tr("Argument Count"), str(codeInfo["argcount"])])
796 QTreeWidgetItem(self.codeInfoWidget, [
797 self.tr("Positional-only Arguments"),
798 str(codeInfo["posonlyargcount"])])
799 QTreeWidgetItem(self.codeInfoWidget, [
800 self.tr("Keyword-only arguments"),
801 str(codeInfo["kwonlyargcount"])])
802 QTreeWidgetItem(self.codeInfoWidget, [
803 self.tr("Number of Locals"), str(codeInfo["nlocals"])])
804 QTreeWidgetItem(self.codeInfoWidget, [
805 self.tr("Stack Size"), str(codeInfo["stacksize"])])
806 QTreeWidgetItem(self.codeInfoWidget, [
807 self.tr("Flags"), codeInfo["flags"]])
808 if codeInfo["consts"]:
809 createCodeInfoItems(self.tr("Constants"),
810 codeInfo["consts"])
811 if codeInfo["names"]:
812 createCodeInfoItems(self.tr("Names"),
813 codeInfo["names"])
814 if codeInfo["varnames"]:
815 createCodeInfoItems(self.tr("Variable Names"),
816 codeInfo["varnames"])
817 if codeInfo["freevars"]:
818 createCodeInfoItems(self.tr("Free Variables"),
819 codeInfo["freevars"])
820 if codeInfo["cellvars"]:
821 createCodeInfoItems(self.tr("Cell Variables"),
822 codeInfo["cellvars"])
823
824 QTimer.singleShot(0, self.__resizeCodeInfoColumns)
825
826 def __resizeCodeInfoColumns(self):
827 """
828 Private method to resize the columns of the code info widget to
829 suitable values.
830 """
831 for col in range(self.codeInfoWidget.columnCount()):
832 self.codeInfoWidget.resizeColumnToContents(col)
833
834 def __expandAllCodeInfo(self):
835 """
836 Private slot to expand all items of the code info widget.
837 """
838 block = self.codeInfoWidget.blockSignals(True)
839 self.codeInfoWidget.expandAll()
840 self.codeInfoWidget.blockSignals(block)
841 self.__resizeCodeInfoColumns()
842
843 def __collapseAllCodeInfo(self):
844 """
845 Private slot to collapse all items of the code info widget.
846 """
847 block = self.codeInfoWidget.blockSignals(True)
848 self.codeInfoWidget.collapseAll()
849 self.codeInfoWidget.blockSignals(block)
850 self.__resizeCodeInfoColumns()
851
852 def __codeInfoContextMenuRequested(self, coord):
853 """
854 Private slot to show the context menu of the code info widget.
855
856 @param coord position of the mouse pointer
857 @type QPoint
858 """
859 if self.disWidget.topLevelItemCount() > 0:
860 # don't show context menu on empty list
861 coord = self.codeInfoWidget.mapToGlobal(coord)
862 self.__codeInfoMenu.popup(coord)

eric ide

mercurial