eric6/Debugger/VariablesViewer.py

branch
maintenance
changeset 8273
698ae46f40a4
parent 8184
913dd0c49b03
parent 8240
93b8a353c4bf
child 8450
be7369a19dc9
equal deleted inserted replaced
8190:fb0ef164f536 8273:698ae46f40a4
7 Module implementing the variables viewer view based on QTreeView. 7 Module implementing the variables viewer view based on QTreeView.
8 """ 8 """
9 9
10 import ast 10 import ast
11 import re 11 import re
12 import contextlib
12 13
13 from PyQt5.QtCore import ( 14 from PyQt5.QtCore import (
14 Qt, QAbstractItemModel, QModelIndex, QCoreApplication, 15 Qt, QAbstractItemModel, QModelIndex, QCoreApplication,
15 QSortFilterProxyModel, pyqtSignal 16 QSortFilterProxyModel, pyqtSignal
16 ) 17 )
26 import Utilities 27 import Utilities
27 28
28 SORT_ROLE = Qt.ItemDataRole.UserRole 29 SORT_ROLE = Qt.ItemDataRole.UserRole
29 30
30 31
31 class VariableItem(object): 32 class VariableItem:
32 """ 33 """
33 Class implementing the data structure for all variable items. 34 Class implementing the data structure for all variable items.
34 """ 35 """
35 Type2Indicators = { 36 Type2Indicators = {
36 # Python types 37 # Python types
143 """ 144 """
144 # Python class? 145 # Python class?
145 if dtype.startswith('class '): 146 if dtype.startswith('class '):
146 dtype = dtype[7:-1] 147 dtype = dtype[7:-1]
147 # Qt related stuff? 148 # Qt related stuff?
148 elif (dtype.startswith(ConfigQtNames) and 149 elif (
149 dtype.endswith(ConfigKnownQtTypes)): 150 (dtype.startswith(ConfigQtNames) and
150 self.hasChildren = True 151 dtype.endswith(ConfigKnownQtTypes)) or
151 152 dtype in ('instance', 'class')
152 elif dtype in ('instance', 'class'): 153 ):
153 self.hasChildren = True 154 self.hasChildren = True
154 155
155 # Special Qt types should not be expanded infinite 156 # Special Qt types should not be expanded infinite
156 elif ".{0}".format(dtype) in ConfigKnownQtTypes: 157 elif ".{0}".format(dtype) in ConfigKnownQtTypes:
157 self.type = dtype # It's a Qt type, so skipping translation is ok 158 self.type = dtype # It's a Qt type, so skipping translation is ok
199 elif dtype == "Shiboken.EnumType": 200 elif dtype == "Shiboken.EnumType":
200 self.hasChildren = True 201 self.hasChildren = True
201 202
202 elif dtype == 'str': 203 elif dtype == 'str':
203 if VariableItem.rx_nonprintable.search(dvalue) is None: 204 if VariableItem.rx_nonprintable.search(dvalue) is None:
204 try: 205 with contextlib.suppress(Exception):
205 dvalue = ast.literal_eval(dvalue) 206 dvalue = ast.literal_eval(dvalue)
206 except Exception: # secok
207 pass
208 dvalue = str(dvalue) 207 dvalue = str(dvalue)
209 208
210 self.value = dvalue 209 self.value = dvalue
211 210
212 if len(dvalue) > 2048: # 2 kB 211 if len(dvalue) > 2048: # 2 kB
261 @type VariablesViewer 260 @type VariablesViewer
262 @param globalScope flag indicating global (True) or local (False) 261 @param globalScope flag indicating global (True) or local (False)
263 variables 262 variables
264 @type bool 263 @type bool
265 """ 264 """
266 super(VariablesModel, self).__init__() 265 super().__init__()
267 self.treeView = treeView 266 self.treeView = treeView
268 self.proxyModel = treeView.proxyModel 267 self.proxyModel = treeView.proxyModel
269 268
270 self.framenr = -1 269 self.framenr = -1
271 self.openItems = [] 270 self.openItems = []
272 self.closedItems = [] 271 self.closedItems = []
273 272
274 if globalScope: 273 visibility = self.tr("Globals") if globalScope else self.tr("Locals")
275 visibility = self.tr("Globals")
276 else:
277 visibility = self.tr("Locals")
278
279 self.rootNode = VariableItem(None, visibility, self.tr("Type"), 274 self.rootNode = VariableItem(None, visibility, self.tr("Type"),
280 self.tr("Value")) 275 self.tr("Value"))
281 276
282 self.__globalScope = globalScope 277 self.__globalScope = globalScope
283 278
480 @param parentIdx item to reset marker 475 @param parentIdx item to reset marker
481 @type QModelIndex 476 @type QModelIndex
482 @param pathlist full path to the variable 477 @param pathlist full path to the variable
483 @type list of str 478 @type list of str
484 """ 479 """
485 if parentIdx.isValid(): 480 parent = (parentIdx.internalPointer() if parentIdx.isValid()
486 parent = parentIdx.internalPointer() 481 else self.rootNode)
487 else:
488 parent = self.rootNode
489 482
490 parent.newItems.clear() 483 parent.newItems.clear()
491 parent.changedItems.clear() 484 parent.changedItems.clear()
492 485
493 pll = len(pathlist) 486 pll = len(pathlist)
495 posPaths |= {x for x in self.closedItems if len(x) > pll} 488 posPaths |= {x for x in self.closedItems if len(x) > pll}
496 posPaths = {x[pll] for x in posPaths if x[:pll] == pathlist} 489 posPaths = {x[pll] for x in posPaths if x[:pll] == pathlist}
497 490
498 if posPaths: 491 if posPaths:
499 for child in parent.children: 492 for child in parent.children:
500 if child.hasChildren and child.nameWithId in posPaths: 493 if (
501 if child.currentCount >= 0: 494 child.hasChildren and
502 # Discard loaded elements and refresh if still expanded 495 child.nameWithId in posPaths and
503 child.currentCount = -1 496 child.currentCount >= 0
504 child.populated = False 497 ):
505 row = parent.children.index(child) 498 # Discard loaded elements and refresh if still expanded
506 newParentIdx = self.index(row, 0, parentIdx) 499 child.currentCount = -1
507 self.resetModifiedMarker( 500 child.populated = False
508 newParentIdx, pathlist + (child.nameWithId,)) 501 row = parent.children.index(child)
502 newParentIdx = self.index(row, 0, parentIdx)
503 self.resetModifiedMarker(
504 newParentIdx, pathlist + (child.nameWithId,))
509 505
510 self.closedItems = [] 506 self.closedItems = []
511 507
512 # Little quirk: Refresh all visible items to clear the changed marker 508 # Little quirk: Refresh all visible items to clear the changed marker
513 if parentIdx == QModelIndex(): 509 if parentIdx == QModelIndex():
535 @param parent the model parent 531 @param parent the model parent
536 @type QModelIndex 532 @type QModelIndex
537 @return number of rows 533 @return number of rows
538 @rtype int 534 @rtype int
539 """ 535 """
540 if parent.isValid(): 536 node = parent.internalPointer() if parent.isValid() else self.rootNode
541 node = parent.internalPointer()
542 else:
543 node = self.rootNode
544 537
545 return len(node.children) 538 return len(node.children)
546 539
547 def flags(self, index): 540 def flags(self, index):
548 """ 541 """
586 @rtype QModelIndex 579 @rtype QModelIndex
587 """ 580 """
588 if not self.hasIndex(row, column, parent): 581 if not self.hasIndex(row, column, parent):
589 return QModelIndex() 582 return QModelIndex()
590 583
591 if not parent.isValid(): 584 node = parent.internalPointer() if parent.isValid() else self.rootNode
592 node = self.rootNode
593 else:
594 node = parent.internalPointer()
595 585
596 return self.createIndex(row, column, node.children[row]) 586 return self.createIndex(row, column, node.children[row])
597 587
598 def parent(self, child): 588 def parent(self, child):
599 """ 589 """
643 if column == 0: 633 if column == 0:
644 # Sort first column with values from third column 634 # Sort first column with values from third column
645 if role == SORT_ROLE: 635 if role == SORT_ROLE:
646 return node.sort 636 return node.sort
647 return node.name + node.indicator 637 return node.name + node.indicator
648 elif column == 1:
649 return node.valueShort
650 elif column == 2:
651 return node.type
652 elif column == 3:
653 return node.sort
654 else: 638 else:
655 return None 639 return {
640 1: node.valueShort,
641 2: node.type,
642 3: node.sort
643 }.get(column)
656 except AttributeError: 644 except AttributeError:
657 return ['None', '', '', ''][column] 645 return ['None', '', '', ''][column]
658 646
659 elif role == Qt.ItemDataRole.BackgroundRole: 647 elif role == Qt.ItemDataRole.BackgroundRole:
660 if node in node.parent.changedItems: 648 if node in node.parent.changedItems:
721 role != Qt.ItemDataRole.DisplayRole or 709 role != Qt.ItemDataRole.DisplayRole or
722 orientation != Qt.Orientation.Horizontal 710 orientation != Qt.Orientation.Horizontal
723 ): 711 ):
724 return None 712 return None
725 713
726 if section == 0: 714 return {
727 return self.rootNode.name 715 0: self.rootNode.name,
728 elif section == 1: 716 1: self.rootNode.value,
729 return self.rootNode.value 717 2: self.rootNode.type,
730 elif section == 2: 718 3: self.rootNode.sort
731 return self.rootNode.type 719 }.get(section)
732 elif section == 3:
733 return self.rootNode.sort
734
735 return None
736 720
737 def __findPendingItem(self, parent=None, pathlist=()): 721 def __findPendingItem(self, parent=None, pathlist=()):
738 """ 722 """
739 Private method to find the next item to request data from debugger. 723 Private method to find the next item to request data from debugger.
740 724
863 Constructor 847 Constructor
864 848
865 @param parent the parent model index 849 @param parent the parent model index
866 @type QModelIndex 850 @type QModelIndex
867 """ 851 """
868 super(VariablesProxyModel, self).__init__(parent) 852 super().__init__(parent)
869 self.setSortRole(SORT_ROLE) 853 self.setSortRole(SORT_ROLE)
870 854
871 def hasChildren(self, parent): 855 def hasChildren(self, parent):
872 """ 856 """
873 Public method to get a flag if parent has children. 857 Public method to get a flag if parent has children.
926 variables 910 variables
927 @type bool 911 @type bool
928 @param parent the parent 912 @param parent the parent
929 @type QWidget 913 @type QWidget
930 """ 914 """
931 super(VariablesViewer, self).__init__(parent) 915 super().__init__(parent)
932 916
933 self.__debugViewer = viewer 917 self.__debugViewer = viewer
934 self.__globalScope = globalScope 918 self.__globalScope = globalScope
935 self.framenr = 0 919 self.framenr = 0
936 920
1044 1028
1045 @param value current value of the vertical scrollbar 1029 @param value current value of the vertical scrollbar
1046 @type int 1030 @type int
1047 """ 1031 """
1048 self.varModel.getMore() 1032 self.varModel.getMore()
1049 super(VariablesViewer, self).verticalScrollbarValueChanged(value) 1033 super().verticalScrollbarValueChanged(value)
1050 1034
1051 def resizeEvent(self, event): 1035 def resizeEvent(self, event):
1052 """ 1036 """
1053 Protected slot informing about the widget size change. 1037 Protected slot informing about the widget size change.
1054 1038
1055 @param event information 1039 @param event information
1056 @type QResizeEvent 1040 @type QResizeEvent
1057 """ 1041 """
1058 self.varModel.getMore() 1042 self.varModel.getMore()
1059 super(VariablesViewer, self).resizeEvent(event) 1043 super().resizeEvent(event)
1060 1044
1061 def __itemDoubleClicked(self, index): 1045 def __itemDoubleClicked(self, index):
1062 """ 1046 """
1063 Private method called if an item was double clicked. 1047 Private method called if an item was double clicked.
1064 1048

eric ide

mercurial