Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

browseProjects.py 9.3KB

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