import regutil, os import hierlist import win32con, win32ui, win32api import commctrl from pywin.mfc import dialog import glob import pyclbr import pywin.framework.scriptutils import afxres class HLIErrorItem(hierlist.HierListItem): def __init__(self, text): self.text = text hierlist.HierListItem.__init__(self) def GetText(self): return self.text class HLICLBRItem(hierlist.HierListItem): def __init__(self, name, file, lineno, suffix = ""): # If the 'name' object itself has a .name, use it. Not sure # how this happens, but seems pyclbr related. # See PyWin32 bug 817035 self.name = getattr(name, "name", name) self.file = file self.lineno = lineno self.suffix = suffix def __lt__(self, other): return self.name < other.name def __eq__(self, other): return self.name == other.name def GetText(self): return self.name + self.suffix def TakeDefaultAction(self): if self.file: pywin.framework.scriptutils.JumpToDocument(self.file, self.lineno, bScrollToTop=1) else: win32ui.SetStatusText("The source of this object is unknown") def PerformItemSelected(self): if self.file is None: msg = "%s - source can not be located." % (self.name, ) else: msg = "%s defined at line %d of %s" % (self.name, self.lineno, self.file) win32ui.SetStatusText(msg) class HLICLBRClass(HLICLBRItem): def __init__(self, clbrclass, suffix = ""): try: name = clbrclass.name file = clbrclass.file lineno = clbrclass.lineno self.super = clbrclass.super self.methods = clbrclass.methods except AttributeError: name = clbrclass file = lineno = None self.super = []; self.methods = {} HLICLBRItem.__init__(self, name, file, lineno, suffix) def GetSubList(self): ret = [] for c in self.super: ret.append(HLICLBRClass(c, " (Parent class)")) for meth, lineno in self.methods.iteritems(): ret.append(HLICLBRMethod(meth, self.file, lineno, " (method)")) return ret def IsExpandable(self): return len(self.methods) + len(self.super) def GetBitmapColumn(self): return 21 class HLICLBRFunction(HLICLBRClass): def GetBitmapColumn(self): return 22 class HLICLBRMethod(HLICLBRItem): def GetBitmapColumn(self): return 22 class HLIModuleItem(hierlist.HierListItem): def __init__(self, path): hierlist.HierListItem.__init__(self) self.path = path def GetText(self): return os.path.split(self.path)[1] + " (module)" def IsExpandable(self): return 1 def TakeDefaultAction(self): win32ui.GetApp().OpenDocumentFile( self.path ) def GetBitmapColumn(self): col = 4 # Default try: if win32api.GetFileAttributes(self.path) & win32con.FILE_ATTRIBUTE_READONLY: col = 5 except win32api.error: pass return col def GetSubList(self): mod, path = pywin.framework.scriptutils.GetPackageModuleName(self.path) win32ui.SetStatusText("Building class list - please wait...", 1) win32ui.DoWaitCursor(1) try: try: reader = pyclbr.readmodule_ex # Post 1.5.2 interface. extra_msg = " or functions" except AttributeError: reader = pyclbr.readmodule extra_msg = "" data = reader(mod, [path]) if data: ret = [] for item in data.itervalues(): if item.__class__ != pyclbr.Class: # ie, it is a pyclbr Function instance (only introduced post 1.5.2) ret.append(HLICLBRFunction( item, " (function)" ) ) else: ret.append(HLICLBRClass( item, " (class)") ) ret.sort() return ret else: return [HLIErrorItem("No Python classes%s in module." % (extra_msg,))] finally: win32ui.DoWaitCursor(0) win32ui.SetStatusText(win32ui.LoadString(afxres.AFX_IDS_IDLEMESSAGE)) def MakePathSubList(path): ret = [] for filename in glob.glob(os.path.join(path,'*')): if os.path.isdir(filename) and os.path.isfile(os.path.join(filename, "__init__.py")): ret.append(HLIDirectoryItem(filename, os.path.split(filename)[1])) else: if os.path.splitext(filename)[1].lower() in ['.py', '.pyw']: ret.append(HLIModuleItem(filename)) return ret class HLIDirectoryItem(hierlist.HierListItem): def __init__(self, path, displayName = None, bSubDirs = 0): hierlist.HierListItem.__init__(self) self.path = path self.bSubDirs = bSubDirs if displayName: self.displayName = displayName else: self.displayName = path def IsExpandable(self): return 1 def GetText(self): return self.displayName def GetSubList(self): ret = MakePathSubList(self.path) if os.path.split(self.path)[1] == "win32com": # Complete and utter hack for win32com. try: path = win32api.GetFullPathName(os.path.join(self.path, "..\\win32comext")) ret = ret + MakePathSubList(path) except win32ui.error: pass return ret class HLIProjectRoot(hierlist.HierListItem): def __init__(self, projectName, displayName = None): hierlist.HierListItem.__init__(self) self.projectName = projectName self.displayName = displayName or projectName def GetText(self): return self.displayName def IsExpandable(self): return 1 def GetSubList(self): paths = regutil.GetRegisteredNamedPath(self.projectName) pathList = paths.split(";") if len(pathList)==1: # Single dir - dont bother putting the dir in ret = MakePathSubList(pathList[0]) else: ret = list(map( HLIDirectoryItem, pathList )) return ret class HLIRoot(hierlist.HierListItem): def __init__(self): hierlist.HierListItem.__init__(self) def IsExpandable(self): return 1 def GetSubList(self): keyStr = regutil.BuildDefaultPythonKey() + "\\PythonPath" hKey = win32api.RegOpenKey(regutil.GetRootKey(), keyStr) try: ret = [] ret.append(HLIProjectRoot("", "Standard Python Library")) # The core path. index = 0 while 1: try: ret.append(HLIProjectRoot(win32api.RegEnumKey(hKey, index))) index = index + 1 except win32api.error: break return ret finally: win32api.RegCloseKey(hKey) class dynamic_browser (dialog.Dialog): style = win32con.WS_OVERLAPPEDWINDOW | win32con.WS_VISIBLE cs = ( win32con.WS_CHILD | win32con.WS_VISIBLE | commctrl.TVS_HASLINES | commctrl.TVS_LINESATROOT | commctrl.TVS_HASBUTTONS ) dt = [ ["Python Projects", (0, 0, 200, 200), style, None, (8, "MS Sans Serif")], ["SysTreeView32", None, win32ui.IDC_LIST1, (0, 0, 200, 200), cs] ] def __init__ (self, hli_root): dialog.Dialog.__init__ (self, self.dt) self.hier_list = hierlist.HierListWithItems ( hli_root, win32ui.IDB_BROWSER_HIER ) self.HookMessage (self.on_size, win32con.WM_SIZE) def OnInitDialog (self): self.hier_list.HierInit (self) return dialog.Dialog.OnInitDialog (self) def on_size (self, params): lparam = params[3] w = win32api.LOWORD(lparam) h = win32api.HIWORD(lparam) self.GetDlgItem (win32ui.IDC_LIST1).MoveWindow((0,0,w,h)) def BrowseDialog(): root = HLIRoot() if not root.IsExpandable(): raise TypeError("Browse() argument must have __dict__ attribute, or be a Browser supported type") dlg = dynamic_browser (root) dlg.CreateWindow() def DockableBrowserCreator(parent): root = HLIRoot() hl = hierlist.HierListWithItems ( root, win32ui.IDB_BROWSER_HIER ) style = win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.WS_BORDER | commctrl.TVS_HASLINES | commctrl.TVS_LINESATROOT | commctrl.TVS_HASBUTTONS control = win32ui.CreateTreeCtrl() control.CreateWindow(style, (0, 0, 150, 300), parent, win32ui.IDC_LIST1) list = hl.HierInit (parent, control) return control def DockablePathBrowser(): import pywin.docking.DockingBar bar = pywin.docking.DockingBar.DockingBar() bar.CreateWindow(win32ui.GetMainFrame(), DockableBrowserCreator, "Path Browser", 0x8e0a) bar.SetBarStyle( bar.GetBarStyle()|afxres.CBRS_TOOLTIPS|afxres.CBRS_FLYBY|afxres.CBRS_SIZE_DYNAMIC) bar.EnableDocking(afxres.CBRS_ALIGN_ANY) win32ui.GetMainFrame().DockControlBar(bar) # The "default" entry point Browse = DockablePathBrowser