codekingpro/portable-devtools
115k
1# toolmenu.py2 3import sys4 5import win32api6import win32con7import win32ui8 9from . import app10 11tools = {}12idPos = 10013 14# The default items should no tools menu exist in the INI file.15defaultToolMenuItems = [16 ("Browser", "win32ui.GetApp().OnViewBrowse(0,0)"),17 (18 "Browse PythonPath",19 "from pywin.tools import browseProjects;browseProjects.Browse()",20 ),21 ("Edit Python Path", "from pywin.tools import regedit;regedit.EditRegistry()"),22 ("COM Makepy utility", "from win32com.client import makepy;makepy.main()"),23 (24 "COM Browser",25 "from win32com.client import combrowse;combrowse.main(modal=False)",26 ),27 (28 "Trace Collector Debugging tool",29 "from pywin.tools import TraceCollector;TraceCollector.MakeOutputWindow()",30 ),31]32 33 34def LoadToolMenuItems():35 # Load from the registry.36 items = []37 lookNo = 138 while 1:39 menu = win32ui.GetProfileVal("Tools Menu\\%s" % lookNo, "", "")40 if menu == "":41 break42 cmd = win32ui.GetProfileVal("Tools Menu\\%s" % lookNo, "Command", "")43 items.append((menu, cmd))44 lookNo = lookNo + 145 46 if len(items) == 0:47 items = defaultToolMenuItems48 return items49 50 51def WriteToolMenuItems(items):52 # Items is a list of (menu, command)53 # Delete the entire registry tree.54 try:55 mainKey = win32ui.GetAppRegistryKey()56 toolKey = win32api.RegOpenKey(mainKey, "Tools Menu")57 except win32ui.error:58 toolKey = None59 if toolKey is not None:60 while 1:61 try:62 subkey = win32api.RegEnumKey(toolKey, 0)63 except win32api.error:64 break65 win32api.RegDeleteKey(toolKey, subkey)66 # Keys are now removed - write the new ones.67 # But first check if we have the defaults - and if so, dont write anything!68 if items == defaultToolMenuItems:69 return70 itemNo = 171 for menu, cmd in items:72 win32ui.WriteProfileVal("Tools Menu\\%s" % itemNo, "", menu)73 win32ui.WriteProfileVal("Tools Menu\\%s" % itemNo, "Command", cmd)74 itemNo = itemNo + 175 76 77def SetToolsMenu(menu, menuPos=None):78 global tools79 global idPos80 81 # todo - check the menu does not already exist.82 # Create the new menu83 toolsMenu = win32ui.CreatePopupMenu()84 85 # Load from the ini file.86 items = LoadToolMenuItems()87 for menuString, cmd in items:88 tools[idPos] = (menuString, cmd, menuString)89 toolsMenu.AppendMenu(90 win32con.MF_ENABLED | win32con.MF_STRING, idPos, menuString91 )92 win32ui.GetMainFrame().HookCommand(HandleToolCommand, idPos)93 idPos = idPos + 194 95 # Find the correct spot to insert the new tools menu.96 if menuPos is None:97 menuPos = menu.GetMenuItemCount() - 298 if menuPos < 0:99 menuPos = 0100 101 menu.InsertMenu(102 menuPos,103 win32con.MF_BYPOSITION104 | win32con.MF_ENABLED105 | win32con.MF_STRING106 | win32con.MF_POPUP,107 toolsMenu.GetHandle(),108 "&Tools",109 )110 111 112def HandleToolCommand(cmd, code):113 import re114 import traceback115 116 global tools117 (menuString, pyCmd, desc) = tools[cmd]118 win32ui.SetStatusText("Executing tool %s" % desc, 1)119 pyCmd = re.sub("\\\\n", "\n", pyCmd)120 win32ui.DoWaitCursor(1)121 oldFlag = None122 try:123 oldFlag = sys.stdout.template.writeQueueing124 sys.stdout.template.writeQueueing = 0125 except (NameError, AttributeError):126 pass127 128 try:129 exec("%s\n" % pyCmd)130 worked = 1131 except SystemExit:132 # The program raised a SystemExit - ignore it.133 worked = 1134 except:135 print("Failed to execute command:\n%s" % pyCmd)136 traceback.print_exc()137 worked = 0138 if oldFlag is not None:139 sys.stdout.template.writeQueueing = oldFlag140 win32ui.DoWaitCursor(0)141 if worked:142 text = "Completed successfully."143 else:144 text = "Error executing %s." % desc145 win32ui.SetStatusText(text, 1)146 147 148# The property page for maintaing the items on the Tools menu.149import commctrl150from pywin.mfc import dialog151 152if win32ui.UNICODE:153 LVN_ENDLABELEDIT = commctrl.LVN_ENDLABELEDITW154else:155 LVN_ENDLABELEDIT = commctrl.LVN_ENDLABELEDITA156 157 158class ToolMenuPropPage(dialog.PropertyPage):159 def __init__(self):160 self.bImChangingEditControls = 0 # Am I programatically changing the controls?161 dialog.PropertyPage.__init__(self, win32ui.IDD_PP_TOOLMENU)162 163 def OnInitDialog(self):164 self.editMenuCommand = self.GetDlgItem(win32ui.IDC_EDIT2)165 self.butNew = self.GetDlgItem(win32ui.IDC_BUTTON3)166 167 # Now hook the change notification messages for the edit controls.168 self.HookCommand(self.OnCommandEditControls, win32ui.IDC_EDIT1)169 self.HookCommand(self.OnCommandEditControls, win32ui.IDC_EDIT2)170 171 self.HookNotify(self.OnNotifyListControl, commctrl.LVN_ITEMCHANGED)172 self.HookNotify(self.OnNotifyListControlEndLabelEdit, commctrl.LVN_ENDLABELEDIT)173 174 # Hook the button clicks.175 self.HookCommand(self.OnButtonNew, win32ui.IDC_BUTTON3) # New Item176 self.HookCommand(self.OnButtonDelete, win32ui.IDC_BUTTON4) # Delete item177 self.HookCommand(self.OnButtonMove, win32ui.IDC_BUTTON1) # Move up178 self.HookCommand(self.OnButtonMove, win32ui.IDC_BUTTON2) # Move down179 180 # Setup the columns in the list control181 lc = self.GetDlgItem(win32ui.IDC_LIST1)182 rect = lc.GetWindowRect()183 cx = rect[2] - rect[0]184 colSize = cx / 2 - win32api.GetSystemMetrics(win32con.SM_CXBORDER) - 1185 186 item = commctrl.LVCFMT_LEFT, colSize, "Menu Text"187 lc.InsertColumn(0, item)188 189 item = commctrl.LVCFMT_LEFT, colSize, "Python Command"190 lc.InsertColumn(1, item)191 192 # Insert the existing tools menu193 itemNo = 0194 for desc, cmd in LoadToolMenuItems():195 lc.InsertItem(itemNo, desc)196 lc.SetItemText(itemNo, 1, cmd)197 itemNo = itemNo + 1198 199 self.listControl = lc200 return dialog.PropertyPage.OnInitDialog(self)201 202 def OnOK(self):203 # Write the menu back to the registry.204 items = []205 itemLook = 0206 while 1:207 try:208 text = self.listControl.GetItemText(itemLook, 0)209 if not text:210 break211 items.append((text, self.listControl.GetItemText(itemLook, 1)))212 except win32ui.error:213 # no more items!214 break215 itemLook = itemLook + 1216 WriteToolMenuItems(items)217 return self._obj_.OnOK()218 219 def OnCommandEditControls(self, id, cmd):220 # print "OnEditControls", id, cmd221 if cmd == win32con.EN_CHANGE and not self.bImChangingEditControls:222 itemNo = self.listControl.GetNextItem(-1, commctrl.LVNI_SELECTED)223 newText = self.editMenuCommand.GetWindowText()224 self.listControl.SetItemText(itemNo, 1, newText)225 226 return 0227 228 def OnNotifyListControlEndLabelEdit(self, id, cmd):229 newText = self.listControl.GetEditControl().GetWindowText()230 itemNo = self.listControl.GetNextItem(-1, commctrl.LVNI_SELECTED)231 self.listControl.SetItemText(itemNo, 0, newText)232 233 def OnNotifyListControl(self, id, cmd):234 # print id, cmd235 try:236 itemNo = self.listControl.GetNextItem(-1, commctrl.LVNI_SELECTED)237 except win32ui.error: # No selection!238 return239 240 self.bImChangingEditControls = 1241 try:242 item = self.listControl.GetItem(itemNo, 1)243 self.editMenuCommand.SetWindowText(item[4])244 finally:245 self.bImChangingEditControls = 0246 247 return 0 # we have handled this!248 249 def OnButtonNew(self, id, cmd):250 if cmd == win32con.BN_CLICKED:251 newIndex = self.listControl.GetItemCount()252 self.listControl.InsertItem(newIndex, "Click to edit the text")253 self.listControl.EnsureVisible(newIndex, 0)254 255 def OnButtonMove(self, id, cmd):256 if cmd == win32con.BN_CLICKED:257 try:258 itemNo = self.listControl.GetNextItem(-1, commctrl.LVNI_SELECTED)259 except win32ui.error:260 return261 menu = self.listControl.GetItemText(itemNo, 0)262 cmd = self.listControl.GetItemText(itemNo, 1)263 if id == win32ui.IDC_BUTTON1:264 # Move up265 if itemNo > 0:266 self.listControl.DeleteItem(itemNo)267 # reinsert it.268 self.listControl.InsertItem(itemNo - 1, menu)269 self.listControl.SetItemText(itemNo - 1, 1, cmd)270 else:271 # Move down.272 if itemNo < self.listControl.GetItemCount() - 1:273 self.listControl.DeleteItem(itemNo)274 # reinsert it.275 self.listControl.InsertItem(itemNo + 1, menu)276 self.listControl.SetItemText(itemNo + 1, 1, cmd)277 278 def OnButtonDelete(self, id, cmd):279 if cmd == win32con.BN_CLICKED:280 try:281 itemNo = self.listControl.GetNextItem(-1, commctrl.LVNI_SELECTED)282 except win32ui.error: # No selection!283 return284 self.listControl.DeleteItem(itemNo)285 