1 #---------------------------------------------------------------------------- 
   2 # Name:         ExtensionService.py 
   3 # Purpose:      Extension Service for IDE 
   9 # Copyright:    (c) 2005 ActiveGrid, Inc. 
  10 # License:      wxWindows License 
  11 #---------------------------------------------------------------------------- 
  14 import wx
.lib
.pydocview
 
  27 EXTENSIONS_CONFIG_STRING 
= "Extensions" 
  31 # TODO: Redo extensions menu on OK, or provide alert that it won't happen until restart 
  34 #---------------------------------------------------------------------------- 
  36 #---------------------------------------------------------------------------- 
  41     def __init__(self
, menuItemName
): 
  42         self
.menuItemName 
= menuItemName
 
  44         self
.menuItemDesc 
= '' 
  46         self
.commandPreArgs 
= '' 
  47         self
.commandPostArgs 
= '' 
  51 class ExtensionService(wx
.lib
.pydocview
.DocService
): 
  58     def LoadExtensions(self
): 
  59         config 
= wx
.ConfigBase_Get() 
  60         pickledExtensions 
= config
.Read(EXTENSIONS_CONFIG_STRING
) 
  63                 self
._extensions 
= pickle
.loads(pickledExtensions
.encode('ascii')) 
  65                 tp
, val
, tb 
= sys
.exc_info() 
  66                 traceback
.print_exception(tp
,val
,tb
) 
  72     def SaveExtensions(self
): 
  73         config 
= wx
.ConfigBase_Get() 
  74         config
.Write(EXTENSIONS_CONFIG_STRING
, pickle
.dumps(self
._extensions
)) 
  77     def GetExtensions(self
): 
  78         return self
._extensions
 
  81     def SetExtensions(self
, extensions
): 
  82         self
._extensions 
= extensions
 
  85     def InstallControls(self
, frame
, menuBar 
= None, toolBar 
= None, statusBar 
= None, document 
= None): 
  86         toolsMenuIndex 
= menuBar
.FindMenu(_("&Tools")) 
  87         if toolsMenuIndex 
> -1: 
  88             toolsMenu 
= menuBar
.GetMenu(toolsMenuIndex
) 
  93             if toolsMenu
.GetMenuItems(): 
  94                 toolsMenu
.AppendSeparator()             
  95             for ext 
in self
._extensions
: 
  96                 # Append a tool menu item for each extension 
  98                 toolsMenu
.Append(ext
.id, ext
.menuItemName
) 
  99                 wx
.EVT_MENU(frame
, ext
.id, frame
.ProcessEvent
) 
 100                 wx
.EVT_UPDATE_UI(frame
, ext
.id, frame
.ProcessUpdateUIEvent
) 
 102         if toolsMenuIndex 
== -1: 
 103             formatMenuIndex 
= menuBar
.FindMenu(_("&Format")) 
 104             menuBar
.Insert(formatMenuIndex 
+ 1, toolsMenu
, _("&Tools")) 
 106     def ProcessEvent(self
, event
): 
 108         for extension 
in self
._extensions
: 
 109             if id == extension
.id: 
 110                 self
.OnExecuteExtension(extension
) 
 115     def ProcessUpdateUIEvent(self
, event
): 
 117         for extension 
in self
._extensions
: 
 118             if id == extension
.id: 
 119                 if extension
.fileExt
: 
 120                     doc 
= wx
.GetApp().GetDocumentManager().GetCurrentDocument() 
 121                     if doc 
and '*' in extension
.fileExt
: 
 125                         for fileExt 
in extension
.fileExt
: 
 126                             if fileExt 
in doc
.GetDocumentTemplate().GetFileFilter(): 
 134     def OnExecuteExtension(self
, extension
): 
 135         if extension
.fileExt
: 
 136             doc 
= wx
.GetApp().GetDocumentManager().GetCurrentDocument() 
 139             filename 
= doc
.GetFilename() 
 140             ext 
= os
.path
.splitext(filename
)[1] 
 141             if not '*' in extension
.fileExt
: 
 142                 if not ext 
or ext
[1:] not in extension
.fileExt
: 
 144             cmds 
= [extension
.command
] 
 145             if extension
.commandPreArgs
: 
 146                 cmds
.append(extension
.commandPreArgs
) 
 147             cmds
.append(filename
) 
 148             if extension
.commandPostArgs
: 
 149                 cmds
.append(extension
.commandPostArgs
) 
 150             os
.spawnv(os
.P_NOWAIT
, extension
.command
, cmds
) 
 153             cmd 
= extension
.command
 
 154             if extension
.commandPreArgs
: 
 155                 cmd 
= cmd 
+ ' ' + extension
.commandPreArgs
 
 156             if extension
.commandPostArgs
: 
 157                 cmd 
= cmd 
+ ' ' + extension
.commandPostArgs
 
 159             messageService 
= wx
.GetApp().GetService(MessageService
.MessageService
) 
 160             messageService
.ShowWindow() 
 161             view 
= messageService
.GetView() 
 162             for line 
in f
.readlines(): 
 164             view
.GetControl().EnsureCaretVisible() 
 168 class ExtensionOptionsPanel(wx
.Panel
): 
 171     def __init__(self
, parent
, id): 
 172         wx
.Panel
.__init
__(self
, parent
, id) 
 174         extOptionsPanelBorderSizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
 176         extOptionsPanelSizer 
= wx
.FlexGridSizer(cols
=2, hgap
=SPACE
, vgap
=HALF_SPACE
) 
 178         extCtrlSizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
 179         extCtrlSizer
.Add(wx
.StaticText(self
, -1, _("Extensions:")), 0) 
 180         self
._extListBox 
= wx
.ListBox(self
, -1, size
=(-1,185), style
=wx
.LB_SINGLE
) 
 181         self
.Bind(wx
.EVT_LISTBOX
, self
.OnListBoxSelect
, self
._extListBox
) 
 182         extCtrlSizer
.Add(self
._extListBox
, 1, wx
.TOP | wx
.BOTTOM | wx
.EXPAND
, SPACE
)         
 183         buttonSizer 
= wx
.GridSizer(rows
=1, hgap
=10, vgap
=5) 
 184         self
._moveUpButton 
= wx
.Button(self
, -1, _("Move Up")) 
 185         self
.Bind(wx
.EVT_BUTTON
, self
.OnMoveUp
, self
._moveUpButton
) 
 186         buttonSizer
.Add(self
._moveUpButton
, 0) 
 187         self
._moveDownButton 
= wx
.Button(self
, -1, _("Move Down")) 
 188         self
.Bind(wx
.EVT_BUTTON
, self
.OnMoveDown
, self
._moveDownButton
) 
 189         buttonSizer
.Add(self
._moveDownButton
, 0) 
 190         extCtrlSizer
.Add(buttonSizer
, 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, HALF_SPACE
) 
 191         buttonSizer 
= wx
.GridSizer(rows
=1, hgap
=10, vgap
=5) 
 192         self
._addButton 
= wx
.Button(self
, -1, _("Add")) 
 193         self
.Bind(wx
.EVT_BUTTON
, self
.OnAdd
, self
._addButton
) 
 194         buttonSizer
.Add(self
._addButton
, 0) 
 195         self
._deleteButton 
= wx
.Button(self
, wx
.ID_DELETE
) 
 196         self
.Bind(wx
.EVT_BUTTON
, self
.OnDelete
, self
._deleteButton
) 
 197         buttonSizer
.Add(self
._deleteButton
, 0) 
 198         extCtrlSizer
.Add(buttonSizer
, 0, wx
.ALIGN_CENTER
) 
 199         extOptionsPanelSizer
.Add(extCtrlSizer
, 0) 
 201         self
._extDetailPanel 
= wx
.Panel(self
) 
 202         staticBox 
= wx
.StaticBox(self
._extDetailPanel
, label
=_("Selected Extension")) 
 203         staticBoxSizer 
= wx
.StaticBoxSizer(staticBox
) 
 204         self
._extDetailPanel
.SetSizer(staticBoxSizer
) 
 205         extDetailSizer 
= wx
.FlexGridSizer(cols
=1, hgap
=5, vgap
=3) 
 206         staticBoxSizer
.AddSizer(extDetailSizer
, 0, wx
.ALL
, 5) 
 208         extDetailSizer
.Add(wx
.StaticText(self
._extDetailPanel
, -1, _("Menu Item Name:"))) 
 209         self
._menuItemNameTextCtrl 
= wx
.TextCtrl(self
._extDetailPanel
, -1, size 
= (-1, -1)) 
 210         extDetailSizer
.Add(self
._menuItemNameTextCtrl
, 1, wx
.EXPAND
) 
 211         self
.Bind(wx
.EVT_TEXT
, self
.SaveCurrentItem
, self
._menuItemNameTextCtrl
)         
 213         extDetailSizer
.Add(wx
.StaticText(self
._extDetailPanel
, -1, _("Menu Item Description:"))) 
 214         self
._menuItemDescTextCtrl 
= wx
.TextCtrl(self
._extDetailPanel
, -1, size 
= (-1, -1)) 
 215         extDetailSizer
.Add(self
._menuItemDescTextCtrl
, 1, wx
.EXPAND
) 
 217         extDetailSizer
.Add(wx
.StaticText(self
._extDetailPanel
, -1, _("Command Path:"))) 
 218         self
._commandTextCtrl 
= wx
.TextCtrl(self
._extDetailPanel
, -1, size 
= (-1, -1))         
 219         findFileButton 
= wx
.Button(self
._extDetailPanel
, -1, _("Browse...")) 
 220         def OnBrowseButton(event
): 
 221             fileDlg 
= wx
.FileDialog(self
, _("Choose an Executable:"), style
=wx
.OPEN | wx
.HIDE_READONLY
) 
 222             path 
= self
._commandTextCtrl
.GetValue() 
 224                 fileDlg
.SetPath(path
) 
 225             if fileDlg
.ShowModal() == wx
.ID_OK
: 
 226                 self
._commandTextCtrl
.SetValue(fileDlg
.GetPath()) 
 227                 self
._commandTextCtrl
.SetInsertionPointEnd() 
 229         wx
.EVT_BUTTON(findFileButton
, -1, OnBrowseButton
) 
 230         hsizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
 231         hsizer
.Add(self
._commandTextCtrl
, 1, wx
.EXPAND
) 
 232         hsizer
.Add(findFileButton
, 0, wx
.LEFT
, HALF_SPACE
) 
 233         extDetailSizer
.Add(hsizer
, 0) 
 235         extDetailSizer
.Add(wx
.StaticText(self
._extDetailPanel
, -1, _("Command Pre Arguments:"))) 
 236         self
._commandPreArgsTextCtrl 
= wx
.TextCtrl(self
._extDetailPanel
, -1, size 
= (-1, -1)) 
 237         extDetailSizer
.Add(self
._commandPreArgsTextCtrl
, 1, wx
.EXPAND
) 
 239         extDetailSizer
.Add(wx
.StaticText(self
._extDetailPanel
, -1, _("Command Post Arguments:"))) 
 240         self
._commandPostArgsTextCtrl 
= wx
.TextCtrl(self
._extDetailPanel
, -1, size 
= (-1, -1)) 
 241         extDetailSizer
.Add(self
._commandPostArgsTextCtrl
, 1, wx
.EXPAND
) 
 243         extDetailSizer
.Add(wx
.StaticText(self
._extDetailPanel
, -1, _("File Extensions (Comma Separated):"))) 
 244         self
._fileExtTextCtrl 
= wx
.TextCtrl(self
._extDetailPanel
, -1, size 
= (-1, -1)) 
 245         self
._fileExtTextCtrl
.SetToolTipString(_("""For example: "txt, text" or "*" for all files""")) 
 246         extDetailSizer
.Add(self
._fileExtTextCtrl
, 1, wx
.EXPAND
) 
 248         extOptionsPanelSizer
.Add(self
._extDetailPanel
, 0) 
 250         extOptionsPanelBorderSizer
.Add(extOptionsPanelSizer
, 0, wx
.ALL | wx
.EXPAND
, SPACE
) 
 251         self
.SetSizer(extOptionsPanelBorderSizer
) 
 253         parent
.AddPage(self
, _("Extensions")) 
 255         if self
.PopulateItems(): 
 256             self
._extListBox
.SetSelection(0) 
 257         self
.OnListBoxSelect(None) 
 260     def OnOK(self
, optionsDialog
): 
 261         self
.SaveCurrentItem() 
 262         extensionsService 
= wx
.GetApp().GetService(ExtensionService
) 
 263         oldExtensions 
= extensionsService
.GetExtensions() 
 264         extensionsService
.SetExtensions(self
._extensions
) 
 265         extensionsService
.SaveExtensions() 
 266         if oldExtensions
.__repr
__() != self
._extensions
.__repr
__(): 
 267             msgTitle 
= wx
.GetApp().GetAppName() 
 269                 msgTitle 
= _("Document Options") 
 270             wx
.MessageBox(_("Extension changes will not appear until the application is restarted."), 
 272                           wx
.OK | wx
.ICON_INFORMATION
, 
 276     def PopulateItems(self
): 
 277         extensionsService 
= wx
.GetApp().GetService(ExtensionService
) 
 279         self
._extensions 
= copy
.deepcopy(extensionsService
.GetExtensions()) 
 280         for extension 
in self
._extensions
: 
 281             self
._extListBox
.Append(extension
.menuItemName
, extension
) 
 282         self
._currentItem 
= None 
 283         self
._currentItemIndex 
= -1 
 284         return len(self
._extensions
) 
 287     def OnListBoxSelect(self
, event
): 
 288         self
.SaveCurrentItem() 
 289         if not self
._extListBox
.GetSelections(): 
 290             self
._currentItemIndex 
= -1 
 291             self
._currentItem 
= None 
 292             self
._deleteButton
.Enable(False) 
 293             self
._moveUpButton
.Enable(False) 
 294             self
._moveDownButton
.Enable(False) 
 296             self
._currentItemIndex 
= self
._extListBox
.GetSelection() 
 297             self
._currentItem 
= self
._extListBox
.GetClientData(self
._currentItemIndex
) 
 298             self
._deleteButton
.Enable() 
 299             self
._moveUpButton
.Enable(self
._extListBox
.GetCount() > 1 and self
._currentItemIndex 
> 0) 
 300             self
._moveDownButton
.Enable(self
._extListBox
.GetCount() > 1 and self
._currentItemIndex 
< self
._extListBox
.GetCount() - 1) 
 301         self
.LoadItem(self
._currentItem
) 
 304     def SaveCurrentItem(self
, event
=None): 
 305         extension 
= self
._currentItem
 
 307             if extension
.menuItemName 
!= self
._menuItemNameTextCtrl
.GetValue(): 
 308                 extension
.menuItemName 
= self
._menuItemNameTextCtrl
.GetValue() 
 309                 self
._extListBox
.SetString(self
._currentItemIndex
, extension
.menuItemName
) 
 310             extension
.menuItemDesc 
= self
._menuItemDescTextCtrl
.GetValue() 
 311             extension
.command 
= self
._commandTextCtrl
.GetValue() 
 312             extension
.commandPreArgs 
= self
._commandPreArgsTextCtrl
.GetValue() 
 313             extension
.commandPostArgs 
= self
._commandPostArgsTextCtrl
.GetValue() 
 314             fileExt 
= self
._fileExtTextCtrl
.GetValue().replace(' ','') 
 316                 extension
.fileExt 
= None 
 318                 extension
.fileExt 
= fileExt
.split(',') 
 321     def LoadItem(self
, extension
): 
 323             self
._menuItemDescTextCtrl
.SetValue(extension
.menuItemDesc 
or '') 
 324             self
._commandTextCtrl
.SetValue(extension
.command 
or '') 
 325             self
._commandPreArgsTextCtrl
.SetValue(extension
.commandPreArgs 
or '') 
 326             self
._commandPostArgsTextCtrl
.SetValue(extension
.commandPostArgs 
or '') 
 327             if extension
.fileExt
: 
 328                 self
._fileExtTextCtrl
.SetValue(extension
.fileExt
.__repr
__()[1:-1].replace("'",""))  # Make the list a string, strip the brakcet on either side 
 330                 self
._fileExtTextCtrl
.SetValue('') 
 331             self
._menuItemNameTextCtrl
.SetValue(extension
.menuItemName 
or '')  # Do the name last since it triggers the write event that updates the entire item 
 332             self
._extDetailPanel
.Enable() 
 334             self
._menuItemNameTextCtrl
.SetValue('') 
 335             self
._menuItemDescTextCtrl
.SetValue('') 
 336             self
._commandTextCtrl
.SetValue('') 
 337             self
._commandPreArgsTextCtrl
.SetValue('') 
 338             self
._commandPostArgsTextCtrl
.SetValue('') 
 339             self
._fileExtTextCtrl
.SetValue('') 
 340             self
._extDetailPanel
.Enable(False) 
 343     def OnAdd(self
, event
): 
 344         self
.SaveCurrentItem() 
 345         extensionNames 
= map(lambda extension
: extension
.menuItemName
, self
._extensions
) 
 348         while name 
in extensionNames
: 
 350             name 
= _("Untitled %s") % count
 
 351         extension 
= Extension(name
) 
 352         self
._extensions
.append(extension
) 
 353         self
._extListBox
.Append(extension
.menuItemName
, extension
) 
 354         self
._extListBox
.SetSelection(self
._extListBox
.GetCount() - 1) 
 355         self
.OnListBoxSelect(None) 
 356         self
._menuItemNameTextCtrl
.SetFocus() 
 357         self
._menuItemNameTextCtrl
.SetSelection(-1, -1) 
 360     def OnDelete(self
, event
): 
 361         self
._extListBox
.Delete(self
._currentItemIndex
) 
 362         self
._extensions
.remove(self
._currentItem
)     
 363         self
._currentItemIndex 
= min(self
._currentItemIndex
, self
._extListBox
.GetCount() - 1) 
 364         if self
._currentItemIndex 
> -1: 
 365             self
._extListBox
.SetSelection(self
._currentItemIndex
) 
 366         self
._currentItem 
= None  # Don't update it since it no longer exists 
 367         self
.OnListBoxSelect(None) 
 370     def OnMoveUp(self
, event
): 
 371         itemAboveString 
= self
._extListBox
.GetString(self
._currentItemIndex 
- 1) 
 372         itemAboveData 
= self
._extListBox
.GetClientData(self
._currentItemIndex 
- 1) 
 373         self
._extListBox
.Delete(self
._currentItemIndex 
- 1) 
 374         self
._extListBox
.Insert(itemAboveString
, self
._currentItemIndex
) 
 375         self
._extListBox
.SetClientData(self
._currentItemIndex
, itemAboveData
) 
 376         self
._currentItemIndex 
= self
._currentItemIndex 
- 1 
 377         self
.OnListBoxSelect(None) # Reset buttons 
 380     def OnMoveDown(self
, event
): 
 381         itemBelowString 
= self
._extListBox
.GetString(self
._currentItemIndex 
+ 1) 
 382         itemBelowData 
= self
._extListBox
.GetClientData(self
._currentItemIndex 
+ 1) 
 383         self
._extListBox
.Delete(self
._currentItemIndex 
+ 1) 
 384         self
._extListBox
.Insert(itemBelowString
, self
._currentItemIndex
) 
 385         self
._extListBox
.SetClientData(self
._currentItemIndex
, itemBelowData
) 
 386         self
._currentItemIndex 
= self
._currentItemIndex 
+ 1 
 387         self
.OnListBoxSelect(None) # Reset buttons