261 lines
8.2 KiB
Python
261 lines
8.2 KiB
Python
|
import regutil, os
|
||
|
from . 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.items():
|
||
|
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.values():
|
||
|
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
|