ModuleBrowser.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. # ModuleBrowser.py - A view that provides a module browser for an editor document.
  2. import pywin.mfc.docview
  3. import win32ui
  4. import win32con
  5. import commctrl
  6. import win32api
  7. from pywin.tools import hierlist, browser
  8. import pywin.framework.scriptutils
  9. import afxres
  10. import pyclbr
  11. class HierListCLBRModule(hierlist.HierListItem):
  12. def __init__(self, modName, clbrdata):
  13. self.modName = modName
  14. self.clbrdata = clbrdata
  15. def GetText(self):
  16. return self.modName
  17. def GetSubList(self):
  18. ret = []
  19. for item in self.clbrdata.itervalues():
  20. if item.__class__ != pyclbr.Class: # ie, it is a pyclbr Function instance (only introduced post 1.5.2)
  21. ret.append(HierListCLBRFunction( item ) )
  22. else:
  23. ret.append(HierListCLBRClass( item) )
  24. ret.sort()
  25. return ret
  26. def IsExpandable(self):
  27. return 1
  28. class HierListCLBRItem(hierlist.HierListItem):
  29. def __init__(self, name, file, lineno, suffix = ""):
  30. self.name = str(name)
  31. self.file = file
  32. self.lineno = lineno
  33. self.suffix = suffix
  34. def __lt__(self, other):
  35. return self.name < other.name
  36. def __eq__(self, other):
  37. return self.name == other.name
  38. def GetText(self):
  39. return self.name + self.suffix
  40. def TakeDefaultAction(self):
  41. if self.file:
  42. pywin.framework.scriptutils.JumpToDocument(self.file, self.lineno, bScrollToTop = 1)
  43. else:
  44. win32ui.SetStatusText("Can not locate the source code for this object.")
  45. def PerformItemSelected(self):
  46. if self.file is None:
  47. msg = "%s - source can not be located." % (self.name, )
  48. else:
  49. msg = "%s defined at line %d of %s" % (self.name, self.lineno, self.file)
  50. win32ui.SetStatusText(msg)
  51. class HierListCLBRClass(HierListCLBRItem):
  52. def __init__(self, clbrclass, suffix = ""):
  53. try:
  54. name = clbrclass.name
  55. file = clbrclass.file
  56. lineno = clbrclass.lineno
  57. self.super = clbrclass.super
  58. self.methods = clbrclass.methods
  59. except AttributeError:
  60. name = clbrclass
  61. file = lineno = None
  62. self.super = []; self.methods = {}
  63. HierListCLBRItem.__init__(self, name, file, lineno, suffix)
  64. def GetSubList(self):
  65. r1 = []
  66. for c in self.super:
  67. r1.append(HierListCLBRClass(c, " (Parent class)"))
  68. r1.sort()
  69. r2=[]
  70. for meth, lineno in self.methods.iteritems():
  71. r2.append(HierListCLBRMethod(meth, self.file, lineno))
  72. r2.sort()
  73. return r1+r2
  74. def IsExpandable(self):
  75. return len(self.methods) + len(self.super)
  76. def GetBitmapColumn(self):
  77. return 21
  78. class HierListCLBRFunction(HierListCLBRItem):
  79. def __init__(self, clbrfunc, suffix = ""):
  80. name = clbrfunc.name
  81. file = clbrfunc.file
  82. lineno = clbrfunc.lineno
  83. HierListCLBRItem.__init__(self, name, file, lineno, suffix)
  84. def GetBitmapColumn(self):
  85. return 22
  86. class HierListCLBRMethod(HierListCLBRItem):
  87. def GetBitmapColumn(self):
  88. return 22
  89. class HierListCLBRErrorItem(hierlist.HierListItem):
  90. def __init__(self, text):
  91. self.text = text
  92. def GetText(self):
  93. return self.text
  94. def GetSubList(self):
  95. return [HierListCLBRErrorItem(self.text)]
  96. def IsExpandable(self):
  97. return 0
  98. class HierListCLBRErrorRoot(HierListCLBRErrorItem):
  99. def IsExpandable(self):
  100. return 1
  101. class BrowserView(pywin.mfc.docview.TreeView):
  102. def OnInitialUpdate(self):
  103. self.list = None
  104. rc = self._obj_.OnInitialUpdate()
  105. self.HookMessage(self.OnSize, win32con.WM_SIZE)
  106. self.bDirty = 0
  107. self.destroying = 0
  108. return rc
  109. def DestroyBrowser(self):
  110. self.DestroyList()
  111. def OnActivateView(self, activate, av, dv):
  112. # print "AV", self.bDirty, activate
  113. if activate:
  114. self.CheckRefreshList()
  115. return self._obj_.OnActivateView(activate, av, dv)
  116. def _MakeRoot(self):
  117. path = self.GetDocument().GetPathName()
  118. if not path:
  119. return HierListCLBRErrorRoot("Error: Can not browse a file until it is saved")
  120. else:
  121. mod, path = pywin.framework.scriptutils.GetPackageModuleName(path)
  122. if self.bDirty:
  123. what = "Refreshing"
  124. # Hack for pyclbr being too smart
  125. try:
  126. del pyclbr._modules[mod]
  127. except (KeyError, AttributeError):
  128. pass
  129. else:
  130. what = "Building"
  131. win32ui.SetStatusText("%s class list - please wait..." % (what,), 1)
  132. win32ui.DoWaitCursor(1)
  133. try:
  134. reader = pyclbr.readmodule_ex # new version post 1.5.2
  135. except AttributeError:
  136. reader = pyclbr.readmodule
  137. try:
  138. data = reader(mod, [path])
  139. if data:
  140. return HierListCLBRModule(mod, data)
  141. else:
  142. return HierListCLBRErrorRoot("No Python classes in module.")
  143. finally:
  144. win32ui.DoWaitCursor(0)
  145. win32ui.SetStatusText(win32ui.LoadString(afxres.AFX_IDS_IDLEMESSAGE))
  146. def DestroyList(self):
  147. self.destroying = 1
  148. list = getattr(self, "list", None) # If the document was not successfully opened, we may not have a list.
  149. self.list = None
  150. if list is not None:
  151. list.HierTerm()
  152. self.destroying = 0
  153. def CheckMadeList(self):
  154. if self.list is not None or self.destroying: return
  155. self.rootitem = root = self._MakeRoot()
  156. self.list = list = hierlist.HierListWithItems( root, win32ui.IDB_BROWSER_HIER)
  157. list.HierInit(self.GetParentFrame(), self)
  158. list.SetStyle(commctrl.TVS_HASLINES | commctrl.TVS_LINESATROOT | commctrl.TVS_HASBUTTONS)
  159. def CheckRefreshList(self):
  160. if self.bDirty:
  161. if self.list is None:
  162. self.CheckMadeList()
  163. else:
  164. new_root = self._MakeRoot()
  165. if self.rootitem.__class__==new_root.__class__==HierListCLBRModule:
  166. self.rootitem.modName = new_root.modName
  167. self.rootitem.clbrdata = new_root.clbrdata
  168. self.list.Refresh()
  169. else:
  170. self.list.AcceptRoot(self._MakeRoot())
  171. self.bDirty = 0
  172. def OnSize(self, params):
  173. lparam = params[3]
  174. w = win32api.LOWORD(lparam)
  175. h = win32api.HIWORD(lparam)
  176. if w != 0:
  177. self.CheckMadeList()
  178. elif w == 0:
  179. self.DestroyList()
  180. return 1
  181. def _UpdateUIForState(self):
  182. self.bDirty = 1