browseProjects.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. import regutil, os
  2. 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.iteritems():
  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.itervalues():
  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