codekingpro/portable-devtools
114k
1# ModuleBrowser.py - A view that provides a module browser for an editor document.2import pyclbr3 4import afxres5import commctrl6import pywin.framework.scriptutils7import pywin.mfc.docview8import win32api9import win32con10import win32ui11from pywin.tools import browser, hierlist12 13 14class HierListCLBRModule(hierlist.HierListItem):15 def __init__(self, modName, clbrdata):16 self.modName = modName17 self.clbrdata = clbrdata18 19 def GetText(self):20 return self.modName21 22 def GetSubList(self):23 ret = []24 for item in self.clbrdata.values():25 if (26 item.__class__ != pyclbr.Class27 ): # ie, it is a pyclbr Function instance (only introduced post 1.5.2)28 ret.append(HierListCLBRFunction(item))29 else:30 ret.append(HierListCLBRClass(item))31 ret.sort()32 return ret33 34 def IsExpandable(self):35 return 136 37 38class HierListCLBRItem(hierlist.HierListItem):39 def __init__(self, name, file, lineno, suffix=""):40 self.name = str(name)41 self.file = file42 self.lineno = lineno43 self.suffix = suffix44 45 def __lt__(self, other):46 return self.name < other.name47 48 def __eq__(self, other):49 return self.name == other.name50 51 def GetText(self):52 return self.name + self.suffix53 54 def TakeDefaultAction(self):55 if self.file:56 pywin.framework.scriptutils.JumpToDocument(57 self.file, self.lineno, bScrollToTop=158 )59 else:60 win32ui.SetStatusText("Can not locate the source code for this object.")61 62 def PerformItemSelected(self):63 if self.file is None:64 msg = "%s - source can not be located." % (self.name,)65 else:66 msg = "%s defined at line %d of %s" % (self.name, self.lineno, self.file)67 win32ui.SetStatusText(msg)68 69 70class HierListCLBRClass(HierListCLBRItem):71 def __init__(self, clbrclass, suffix=""):72 try:73 name = clbrclass.name74 file = clbrclass.file75 lineno = clbrclass.lineno76 self.super = clbrclass.super77 self.methods = clbrclass.methods78 except AttributeError:79 name = clbrclass80 file = lineno = None81 self.super = []82 self.methods = {}83 HierListCLBRItem.__init__(self, name, file, lineno, suffix)84 85 def GetSubList(self):86 r1 = []87 for c in self.super:88 r1.append(HierListCLBRClass(c, " (Parent class)"))89 r1.sort()90 r2 = []91 for meth, lineno in self.methods.items():92 r2.append(HierListCLBRMethod(meth, self.file, lineno))93 r2.sort()94 return r1 + r295 96 def IsExpandable(self):97 return len(self.methods) + len(self.super)98 99 def GetBitmapColumn(self):100 return 21101 102 103class HierListCLBRFunction(HierListCLBRItem):104 def __init__(self, clbrfunc, suffix=""):105 name = clbrfunc.name106 file = clbrfunc.file107 lineno = clbrfunc.lineno108 HierListCLBRItem.__init__(self, name, file, lineno, suffix)109 110 def GetBitmapColumn(self):111 return 22112 113 114class HierListCLBRMethod(HierListCLBRItem):115 def GetBitmapColumn(self):116 return 22117 118 119class HierListCLBRErrorItem(hierlist.HierListItem):120 def __init__(self, text):121 self.text = text122 123 def GetText(self):124 return self.text125 126 def GetSubList(self):127 return [HierListCLBRErrorItem(self.text)]128 129 def IsExpandable(self):130 return 0131 132 133class HierListCLBRErrorRoot(HierListCLBRErrorItem):134 def IsExpandable(self):135 return 1136 137 138class BrowserView(pywin.mfc.docview.TreeView):139 def OnInitialUpdate(self):140 self.list = None141 rc = self._obj_.OnInitialUpdate()142 self.HookMessage(self.OnSize, win32con.WM_SIZE)143 self.bDirty = 0144 self.destroying = 0145 return rc146 147 def DestroyBrowser(self):148 self.DestroyList()149 150 def OnActivateView(self, activate, av, dv):151 # print "AV", self.bDirty, activate152 if activate:153 self.CheckRefreshList()154 return self._obj_.OnActivateView(activate, av, dv)155 156 def _MakeRoot(self):157 path = self.GetDocument().GetPathName()158 if not path:159 return HierListCLBRErrorRoot(160 "Error: Can not browse a file until it is saved"161 )162 else:163 mod, path = pywin.framework.scriptutils.GetPackageModuleName(path)164 if self.bDirty:165 what = "Refreshing"166 # Hack for pyclbr being too smart167 try:168 del pyclbr._modules[mod]169 except (KeyError, AttributeError):170 pass171 else:172 what = "Building"173 win32ui.SetStatusText("%s class list - please wait..." % (what,), 1)174 win32ui.DoWaitCursor(1)175 try:176 reader = pyclbr.readmodule_ex # new version post 1.5.2177 except AttributeError:178 reader = pyclbr.readmodule179 try:180 data = reader(mod, [path])181 if data:182 return HierListCLBRModule(mod, data)183 else:184 return HierListCLBRErrorRoot("No Python classes in module.")185 186 finally:187 win32ui.DoWaitCursor(0)188 win32ui.SetStatusText(win32ui.LoadString(afxres.AFX_IDS_IDLEMESSAGE))189 190 def DestroyList(self):191 self.destroying = 1192 list = getattr(193 self, "list", None194 ) # If the document was not successfully opened, we may not have a list.195 self.list = None196 if list is not None:197 list.HierTerm()198 self.destroying = 0199 200 def CheckMadeList(self):201 if self.list is not None or self.destroying:202 return203 self.rootitem = root = self._MakeRoot()204 self.list = list = hierlist.HierListWithItems(root, win32ui.IDB_BROWSER_HIER)205 list.HierInit(self.GetParentFrame(), self)206 list.SetStyle(207 commctrl.TVS_HASLINES | commctrl.TVS_LINESATROOT | commctrl.TVS_HASBUTTONS208 )209 210 def CheckRefreshList(self):211 if self.bDirty:212 if self.list is None:213 self.CheckMadeList()214 else:215 new_root = self._MakeRoot()216 if self.rootitem.__class__ == new_root.__class__ == HierListCLBRModule:217 self.rootitem.modName = new_root.modName218 self.rootitem.clbrdata = new_root.clbrdata219 self.list.Refresh()220 else:221 self.list.AcceptRoot(self._MakeRoot())222 self.bDirty = 0223 224 def OnSize(self, params):225 lparam = params[3]226 w = win32api.LOWORD(lparam)227 h = win32api.HIWORD(lparam)228 if w != 0:229 self.CheckMadeList()230 elif w == 0:231 self.DestroyList()232 return 1233 234 def _UpdateUIForState(self):235 self.bDirty = 1236 