browseProjects.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. import regutil, os
  2. from . import hierlist
  3. import win32con, win32ui, win32api
  4. import commctrl
  5. from pywin.mfc import dialog
  6. import glob
  7. import pyclbr
  8. import pywin.framework.scriptutils
  9. import afxres
  10. class HLIErrorItem(hierlist.HierListItem):
  11. def __init__(self, text):
  12. self.text = text
  13. hierlist.HierListItem.__init__(self)
  14. def GetText(self):
  15. return self.text
  16. class HLICLBRItem(hierlist.HierListItem):
  17. def __init__(self, name, file, lineno, suffix = ""):
  18. # If the 'name' object itself has a .name, use it. Not sure
  19. # how this happens, but seems pyclbr related.
  20. # See PyWin32 bug 817035
  21. self.name = getattr(name, "name", name)
  22. self.file = file
  23. self.lineno = lineno
  24. self.suffix = suffix
  25. def __lt__(self, other):
  26. return self.name < other.name
  27. def __eq__(self, other):
  28. return self.name == other.name
  29. def GetText(self):
  30. return self.name + self.suffix
  31. def TakeDefaultAction(self):
  32. if self.file:
  33. pywin.framework.scriptutils.JumpToDocument(self.file, self.lineno, bScrollToTop=1)
  34. else:
  35. win32ui.SetStatusText("The source of this object is unknown")
  36. def PerformItemSelected(self):
  37. if self.file is None:
  38. msg = "%s - source can not be located." % (self.name, )
  39. else:
  40. msg = "%s defined at line %d of %s" % (self.name, self.lineno, self.file)
  41. win32ui.SetStatusText(msg)
  42. class HLICLBRClass(HLICLBRItem):
  43. def __init__(self, clbrclass, suffix = ""):
  44. try:
  45. name = clbrclass.name
  46. file = clbrclass.file
  47. lineno = clbrclass.lineno
  48. self.super = clbrclass.super
  49. self.methods = clbrclass.methods
  50. except AttributeError:
  51. name = clbrclass
  52. file = lineno = None
  53. self.super = []; self.methods = {}
  54. HLICLBRItem.__init__(self, name, file, lineno, suffix)
  55. def GetSubList(self):
  56. ret = []
  57. for c in self.super:
  58. ret.append(HLICLBRClass(c, " (Parent class)"))
  59. for meth, lineno in self.methods.items():
  60. ret.append(HLICLBRMethod(meth, self.file, lineno, " (method)"))
  61. return ret
  62. def IsExpandable(self):
  63. return len(self.methods) + len(self.super)
  64. def GetBitmapColumn(self):
  65. return 21
  66. class HLICLBRFunction(HLICLBRClass):
  67. def GetBitmapColumn(self):
  68. return 22
  69. class HLICLBRMethod(HLICLBRItem):
  70. def GetBitmapColumn(self):
  71. return 22
  72. class HLIModuleItem(hierlist.HierListItem):
  73. def __init__(self, path):
  74. hierlist.HierListItem.__init__(self)
  75. self.path = path
  76. def GetText(self):
  77. return os.path.split(self.path)[1] + " (module)"
  78. def IsExpandable(self):
  79. return 1
  80. def TakeDefaultAction(self):
  81. win32ui.GetApp().OpenDocumentFile( self.path )
  82. def GetBitmapColumn(self):
  83. col = 4 # Default
  84. try:
  85. if win32api.GetFileAttributes(self.path) & win32con.FILE_ATTRIBUTE_READONLY:
  86. col = 5
  87. except win32api.error:
  88. pass
  89. return col
  90. def GetSubList(self):
  91. mod, path = pywin.framework.scriptutils.GetPackageModuleName(self.path)
  92. win32ui.SetStatusText("Building class list - please wait...", 1)
  93. win32ui.DoWaitCursor(1)
  94. try:
  95. try:
  96. reader = pyclbr.readmodule_ex # Post 1.5.2 interface.
  97. extra_msg = " or functions"
  98. except AttributeError:
  99. reader = pyclbr.readmodule
  100. extra_msg = ""
  101. data = reader(mod, [path])
  102. if data:
  103. ret = []
  104. for item in data.values():
  105. if item.__class__ != pyclbr.Class: # ie, it is a pyclbr Function instance (only introduced post 1.5.2)
  106. ret.append(HLICLBRFunction( item, " (function)" ) )
  107. else:
  108. ret.append(HLICLBRClass( item, " (class)") )
  109. ret.sort()
  110. return ret
  111. else:
  112. return [HLIErrorItem("No Python classes%s in module." % (extra_msg,))]
  113. finally:
  114. win32ui.DoWaitCursor(0)
  115. win32ui.SetStatusText(win32ui.LoadString(afxres.AFX_IDS_IDLEMESSAGE))
  116. def MakePathSubList(path):
  117. ret = []
  118. for filename in glob.glob(os.path.join(path,'*')):
  119. if os.path.isdir(filename) and os.path.isfile(os.path.join(filename, "__init__.py")):
  120. ret.append(HLIDirectoryItem(filename, os.path.split(filename)[1]))
  121. else:
  122. if os.path.splitext(filename)[1].lower() in ['.py', '.pyw']:
  123. ret.append(HLIModuleItem(filename))
  124. return ret
  125. class HLIDirectoryItem(hierlist.HierListItem):
  126. def __init__(self, path, displayName = None, bSubDirs = 0):
  127. hierlist.HierListItem.__init__(self)
  128. self.path = path
  129. self.bSubDirs = bSubDirs
  130. if displayName:
  131. self.displayName = displayName
  132. else:
  133. self.displayName = path
  134. def IsExpandable(self):
  135. return 1
  136. def GetText(self):
  137. return self.displayName
  138. def GetSubList(self):
  139. ret = MakePathSubList(self.path)
  140. if os.path.split(self.path)[1] == "win32com": # Complete and utter hack for win32com.
  141. try:
  142. path = win32api.GetFullPathName(os.path.join(self.path, "..\\win32comext"))
  143. ret = ret + MakePathSubList(path)
  144. except win32ui.error:
  145. pass
  146. return ret
  147. class HLIProjectRoot(hierlist.HierListItem):
  148. def __init__(self, projectName, displayName = None):
  149. hierlist.HierListItem.__init__(self)
  150. self.projectName = projectName
  151. self.displayName = displayName or projectName
  152. def GetText(self):
  153. return self.displayName
  154. def IsExpandable(self):
  155. return 1
  156. def GetSubList(self):
  157. paths = regutil.GetRegisteredNamedPath(self.projectName)
  158. pathList = paths.split(";")
  159. if len(pathList)==1: # Single dir - dont bother putting the dir in
  160. ret = MakePathSubList(pathList[0])
  161. else:
  162. ret = list(map( HLIDirectoryItem, pathList ))
  163. return ret
  164. class HLIRoot(hierlist.HierListItem):
  165. def __init__(self):
  166. hierlist.HierListItem.__init__(self)
  167. def IsExpandable(self):
  168. return 1
  169. def GetSubList(self):
  170. keyStr = regutil.BuildDefaultPythonKey() + "\\PythonPath"
  171. hKey = win32api.RegOpenKey(regutil.GetRootKey(), keyStr)
  172. try:
  173. ret = []
  174. ret.append(HLIProjectRoot("", "Standard Python Library")) # The core path.
  175. index = 0
  176. while 1:
  177. try:
  178. ret.append(HLIProjectRoot(win32api.RegEnumKey(hKey, index)))
  179. index = index + 1
  180. except win32api.error:
  181. break
  182. return ret
  183. finally:
  184. win32api.RegCloseKey(hKey)
  185. class dynamic_browser (dialog.Dialog):
  186. style = win32con.WS_OVERLAPPEDWINDOW | win32con.WS_VISIBLE
  187. cs = (
  188. win32con.WS_CHILD |
  189. win32con.WS_VISIBLE |
  190. commctrl.TVS_HASLINES |
  191. commctrl.TVS_LINESATROOT |
  192. commctrl.TVS_HASBUTTONS
  193. )
  194. dt = [
  195. ["Python Projects", (0, 0, 200, 200), style, None, (8, "MS Sans Serif")],
  196. ["SysTreeView32", None, win32ui.IDC_LIST1, (0, 0, 200, 200), cs]
  197. ]
  198. def __init__ (self, hli_root):
  199. dialog.Dialog.__init__ (self, self.dt)
  200. self.hier_list = hierlist.HierListWithItems (
  201. hli_root,
  202. win32ui.IDB_BROWSER_HIER
  203. )
  204. self.HookMessage (self.on_size, win32con.WM_SIZE)
  205. def OnInitDialog (self):
  206. self.hier_list.HierInit (self)
  207. return dialog.Dialog.OnInitDialog (self)
  208. def on_size (self, params):
  209. lparam = params[3]
  210. w = win32api.LOWORD(lparam)
  211. h = win32api.HIWORD(lparam)
  212. self.GetDlgItem (win32ui.IDC_LIST1).MoveWindow((0,0,w,h))
  213. def BrowseDialog():
  214. root = HLIRoot()
  215. if not root.IsExpandable():
  216. raise TypeError("Browse() argument must have __dict__ attribute, or be a Browser supported type")
  217. dlg = dynamic_browser (root)
  218. dlg.CreateWindow()
  219. def DockableBrowserCreator(parent):
  220. root = HLIRoot()
  221. hl = hierlist.HierListWithItems (
  222. root,
  223. win32ui.IDB_BROWSER_HIER
  224. )
  225. style = win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.WS_BORDER | commctrl.TVS_HASLINES | commctrl.TVS_LINESATROOT | commctrl.TVS_HASBUTTONS
  226. control = win32ui.CreateTreeCtrl()
  227. control.CreateWindow(style, (0, 0, 150, 300), parent, win32ui.IDC_LIST1)
  228. list = hl.HierInit (parent, control)
  229. return control
  230. def DockablePathBrowser():
  231. import pywin.docking.DockingBar
  232. bar = pywin.docking.DockingBar.DockingBar()
  233. bar.CreateWindow(win32ui.GetMainFrame(), DockableBrowserCreator, "Path Browser", 0x8e0a)
  234. bar.SetBarStyle( bar.GetBarStyle()|afxres.CBRS_TOOLTIPS|afxres.CBRS_FLYBY|afxres.CBRS_SIZE_DYNAMIC)
  235. bar.EnableDocking(afxres.CBRS_ALIGN_ANY)
  236. win32ui.GetMainFrame().DockControlBar(bar)
  237. # The "default" entry point
  238. Browse = DockablePathBrowser