#
# Created: 5/23/05
# CVS-ID: $ID:$
-# Copyright: (c) 2005 ActiveGrid, Inc.
+# Copyright: (c) 2005-2006 ActiveGrid, Inc.
# License: wxWindows License
#----------------------------------------------------------------------------
import wx
import wx.lib.pydocview
import MessageService
+import ProjectEditor
import os
import os.path
-import pickle
-
+import activegrid.util.xmlutils as xmlutils
_ = wx.GetTranslation
+#----------------------------------------------------------------------------
+# Constants
+#----------------------------------------------------------------------------
SPACE = 10
HALF_SPACE = 5
-EXTENSIONS_CONFIG_STRING = "Extensions"
-
-
-
-# TODO: Redo extensions menu on OK, or provide alert that it won't happen until restart
-
-
#----------------------------------------------------------------------------
# Classes
#----------------------------------------------------------------------------
class Extension:
-
- def __init__(self, menuItemName):
+
+ def __init__(self, menuItemName=None):
self.menuItemName = menuItemName
self.id = 0
self.menuItemDesc = ''
self.commandPreArgs = ''
self.commandPostArgs = ''
self.fileExt = None
+ self.opOnSelectedFile = True
class ExtensionService(wx.lib.pydocview.DocService):
+ EXTENSIONS_KEY = "/AG_Extensions"
def __init__(self):
self.LoadExtensions()
+ def __getExtensionKeyName(extensionName):
+ return "%s/%s" % (ExtensionService.EXTENSIONS_KEY, extensionName)
+
+
+ __getExtensionKeyName = staticmethod(__getExtensionKeyName)
+
+
def LoadExtensions(self):
+ self._extensions = []
+
+ extensionNames = []
config = wx.ConfigBase_Get()
- pickledExtensions = config.Read(EXTENSIONS_CONFIG_STRING)
- if pickledExtensions:
- try:
- self._extensions = pickle.loads(pickledExtensions.encode('ascii'))
- except:
- tp, val, tb = sys.exc_info()
- traceback.print_exception(tp,val,tb)
- self._extensions = []
- else:
- self._extensions = []
-
+ path = config.GetPath()
+ try:
+ config.SetPath(ExtensionService.EXTENSIONS_KEY)
+ cont, value, index = config.GetFirstEntry()
+ while cont:
+ extensionNames.append(value)
+ cont, value, index = config.GetNextEntry(index)
+ finally:
+ config.SetPath(path)
+
+ for extensionName in extensionNames:
+ extensionData = config.Read(self.__getExtensionKeyName(extensionName))
+ if extensionData:
+ extension = xmlutils.unmarshal(extensionData.encode('utf-8'))
+ self._extensions.append(extension)
+
def SaveExtensions(self):
config = wx.ConfigBase_Get()
- config.Write(EXTENSIONS_CONFIG_STRING, pickle.dumps(self._extensions))
+ config.DeleteGroup(ExtensionService.EXTENSIONS_KEY)
+ for extension in self._extensions:
+ config.Write(self.__getExtensionKeyName(extension.menuItemName), xmlutils.marshal(extension))
def GetExtensions(self):
self._extensions = extensions
+ def CheckSumExtensions(self):
+ return xmlutils.marshal(self._extensions)
+
+
def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None):
toolsMenuIndex = menuBar.FindMenu(_("&Tools"))
if toolsMenuIndex > -1:
toolsMenu = menuBar.GetMenu(toolsMenuIndex)
else:
toolsMenu = wx.Menu()
-
+
if self._extensions:
if toolsMenu.GetMenuItems():
- toolsMenu.AppendSeparator()
+ toolsMenu.AppendSeparator()
for ext in self._extensions:
# Append a tool menu item for each extension
ext.id = wx.NewId()
wx.EVT_UPDATE_UI(frame, ext.id, frame.ProcessUpdateUIEvent)
if toolsMenuIndex == -1:
- formatMenuIndex = menuBar.FindMenu(_("&Format"))
- menuBar.Insert(formatMenuIndex + 1, toolsMenu, _("&Tools"))
+ index = menuBar.FindMenu(_("&Run"))
+ if index == -1:
+ index = menuBar.FindMenu(_("&Project"))
+ if index == -1:
+ index = menuBar.FindMenu(_("&Format"))
+ if index == -1:
+ index = menuBar.FindMenu(_("&View"))
+ menuBar.Insert(index + 1, toolsMenu, _("&Tools"))
+
def ProcessEvent(self, event):
id = event.GetId()
if fileExt in doc.GetDocumentTemplate().GetFileFilter():
event.Enable(True)
return True
+ if extension.opOnSelectedFile and isinstance(doc, ProjectEditor.ProjectDocument):
+ filename = doc.GetFirstView().GetSelectedFile()
+ if filename:
+ template = wx.GetApp().GetDocumentManager().FindTemplateForPath(filename)
+ for fileExt in extension.fileExt:
+ if fileExt in template.GetFileFilter():
+ event.Enable(True)
+ return True
event.Enable(False)
return False
return False
doc = wx.GetApp().GetDocumentManager().GetCurrentDocument()
if not doc:
return
- filename = doc.GetFilename()
+ if extension.opOnSelectedFile and isinstance(doc, ProjectEditor.ProjectDocument):
+ filename = doc.GetFirstView().GetSelectedFile()
+ if not filename:
+ filename = doc.GetFilename()
+ else:
+ filename = doc.GetFilename()
ext = os.path.splitext(filename)[1]
if not '*' in extension.fileExt:
if not ext or ext[1:] not in extension.fileExt:
if extension.commandPostArgs:
cmds.append(extension.commandPostArgs)
os.spawnv(os.P_NOWAIT, extension.command, cmds)
-
+
else:
cmd = extension.command
if extension.commandPreArgs:
view.AddLines(line)
view.GetControl().EnsureCaretVisible()
f.close()
-
+
class ExtensionOptionsPanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id)
-
- extOptionsPanelBorderSizer = wx.BoxSizer(wx.HORIZONTAL)
-
- extOptionsPanelSizer = wx.FlexGridSizer(cols=2, hgap=SPACE, vgap=HALF_SPACE)
-
+
+ extOptionsPanelBorderSizer = wx.BoxSizer(wx.VERTICAL)
+
+ extOptionsPanelSizer = wx.BoxSizer(wx.HORIZONTAL)
+
extCtrlSizer = wx.BoxSizer(wx.VERTICAL)
- extCtrlSizer.Add(wx.StaticText(self, -1, _("Extensions:")), 0)
- self._extListBox = wx.ListBox(self, -1, size=(-1,185), style=wx.LB_SINGLE)
+ extCtrlSizer.Add(wx.StaticText(self, -1, _("External Tools:")), 0, wx.BOTTOM, HALF_SPACE)
+ self._extListBox = wx.ListBox(self, -1, style=wx.LB_SINGLE)
self.Bind(wx.EVT_LISTBOX, self.OnListBoxSelect, self._extListBox)
- extCtrlSizer.Add(self._extListBox, 1, wx.TOP | wx.BOTTOM | wx.EXPAND, SPACE)
- buttonSizer = wx.GridSizer(rows=1, hgap=10, vgap=5)
+ extCtrlSizer.Add(self._extListBox, 1, wx.BOTTOM | wx.EXPAND, SPACE)
+ buttonSizer = wx.GridSizer(cols=2, vgap=HALF_SPACE, hgap=HALF_SPACE)
self._moveUpButton = wx.Button(self, -1, _("Move Up"))
self.Bind(wx.EVT_BUTTON, self.OnMoveUp, self._moveUpButton)
- buttonSizer.Add(self._moveUpButton, 0)
+ buttonSizer.Add(self._moveUpButton, 1, wx.EXPAND)
self._moveDownButton = wx.Button(self, -1, _("Move Down"))
self.Bind(wx.EVT_BUTTON, self.OnMoveDown, self._moveDownButton)
- buttonSizer.Add(self._moveDownButton, 0)
- extCtrlSizer.Add(buttonSizer, 0, wx.ALIGN_CENTER | wx.BOTTOM, HALF_SPACE)
- buttonSizer = wx.GridSizer(rows=1, hgap=10, vgap=5)
- self._addButton = wx.Button(self, -1, _("Add"))
+ buttonSizer.Add(self._moveDownButton, 1, wx.EXPAND)
+ self._addButton = wx.Button(self, wx.ID_ADD)
self.Bind(wx.EVT_BUTTON, self.OnAdd, self._addButton)
- buttonSizer.Add(self._addButton, 0)
- self._deleteButton = wx.Button(self, wx.ID_DELETE)
+ buttonSizer.Add(self._addButton, 1, wx.EXPAND)
+ self._deleteButton = wx.Button(self, wx.ID_DELETE, label=_("Delete")) # get rid of accelerator for letter d in "&Delete"
self.Bind(wx.EVT_BUTTON, self.OnDelete, self._deleteButton)
- buttonSizer.Add(self._deleteButton, 0)
+ buttonSizer.Add(self._deleteButton, 1, wx.EXPAND)
extCtrlSizer.Add(buttonSizer, 0, wx.ALIGN_CENTER)
- extOptionsPanelSizer.Add(extCtrlSizer, 0)
+ extOptionsPanelSizer.Add(extCtrlSizer, 0, wx.EXPAND)
self._extDetailPanel = wx.Panel(self)
- staticBox = wx.StaticBox(self._extDetailPanel, label=_("Selected Extension"))
- staticBoxSizer = wx.StaticBoxSizer(staticBox)
- self._extDetailPanel.SetSizer(staticBoxSizer)
- extDetailSizer = wx.FlexGridSizer(cols=1, hgap=5, vgap=3)
- staticBoxSizer.AddSizer(extDetailSizer, 0, wx.ALL, 5)
+ staticBox = wx.StaticBox(self, label=_("Selected External Tool"))
+ staticBoxSizer = wx.StaticBoxSizer(staticBox, wx.VERTICAL)
+
+ extDetailSizer = wx.FlexGridSizer(cols=2, vgap=5, hgap=5)
+ extDetailSizer.AddGrowableCol(1,1)
- extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Menu Item Name:")))
+ extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Menu Item Name:")), flag=wx.ALIGN_CENTER_VERTICAL)
self._menuItemNameTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1))
- extDetailSizer.Add(self._menuItemNameTextCtrl, 1, wx.EXPAND)
- self.Bind(wx.EVT_TEXT, self.SaveCurrentItem, self._menuItemNameTextCtrl)
+ extDetailSizer.Add(self._menuItemNameTextCtrl, 0, wx.EXPAND)
+ self.Bind(wx.EVT_TEXT, self.SaveCurrentItem, self._menuItemNameTextCtrl)
- extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Menu Item Description:")))
+ extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Menu Item Description:")), flag=wx.ALIGN_CENTER_VERTICAL)
self._menuItemDescTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1))
- extDetailSizer.Add(self._menuItemDescTextCtrl, 1, wx.EXPAND)
+ extDetailSizer.Add(self._menuItemDescTextCtrl, 0, wx.EXPAND)
- extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Path:")))
- self._commandTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1))
+ extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Path:")), flag=wx.ALIGN_CENTER_VERTICAL)
+ self._commandTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1))
findFileButton = wx.Button(self._extDetailPanel, -1, _("Browse..."))
def OnBrowseButton(event):
- fileDlg = wx.FileDialog(self, _("Choose an Executable:"), style=wx.OPEN | wx.HIDE_READONLY)
+ fileDlg = wx.FileDialog(self, _("Choose an Executable:"), style=wx.OPEN|wx.FILE_MUST_EXIST|wx.HIDE_READONLY|wx.CHANGE_DIR)
path = self._commandTextCtrl.GetValue()
if path:
fileDlg.SetPath(path)
+ # fileDlg.CenterOnParent() # wxBug: caused crash with wx.FileDialog
if fileDlg.ShowModal() == wx.ID_OK:
self._commandTextCtrl.SetValue(fileDlg.GetPath())
self._commandTextCtrl.SetInsertionPointEnd()
+ self._commandTextCtrl.SetToolTipString(fileDlg.GetPath())
fileDlg.Destroy()
wx.EVT_BUTTON(findFileButton, -1, OnBrowseButton)
hsizer = wx.BoxSizer(wx.HORIZONTAL)
hsizer.Add(self._commandTextCtrl, 1, wx.EXPAND)
hsizer.Add(findFileButton, 0, wx.LEFT, HALF_SPACE)
- extDetailSizer.Add(hsizer, 0)
+ extDetailSizer.Add(hsizer, 0, wx.EXPAND)
- extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Pre Arguments:")))
+ extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Pre Args:")), flag=wx.ALIGN_CENTER_VERTICAL)
self._commandPreArgsTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1))
- extDetailSizer.Add(self._commandPreArgsTextCtrl, 1, wx.EXPAND)
+ extDetailSizer.Add(self._commandPreArgsTextCtrl, 0, wx.EXPAND)
- extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Post Arguments:")))
+ extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Post Args:")), flag=wx.ALIGN_CENTER_VERTICAL)
self._commandPostArgsTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1))
- extDetailSizer.Add(self._commandPostArgsTextCtrl, 1, wx.EXPAND)
+ extDetailSizer.Add(self._commandPostArgsTextCtrl, 0, wx.EXPAND)
- extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("File Extensions (Comma Separated):")))
+ extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("File Extensions:")), flag=wx.ALIGN_CENTER_VERTICAL)
self._fileExtTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1))
- self._fileExtTextCtrl.SetToolTipString(_("""For example: "txt, text" or "*" for all files"""))
- extDetailSizer.Add(self._fileExtTextCtrl, 1, wx.EXPAND)
+ self._fileExtTextCtrl.SetToolTipString(_("""For example: "txt, text" (comma separated) or "*" for all files"""))
+ extDetailSizer.Add(self._fileExtTextCtrl, 0, wx.EXPAND)
+
+ self._selFileCtrl = wx.CheckBox(self._extDetailPanel, -1, _("Operate on Selected File"))
+ extDetailSizer.Add(self._selFileCtrl, 0, wx.ALIGN_CENTER_VERTICAL|wx.TOP, SPACE)
+ self._selFileCtrl.SetToolTipString(_("If focus is in the project, instead of operating on the project file, operate on the selected file."))
- extOptionsPanelSizer.Add(self._extDetailPanel, 0)
+ self._extDetailPanel.SetSizer(extDetailSizer)
+ staticBoxSizer.Add(self._extDetailPanel, 1, wx.ALL|wx.EXPAND, SPACE)
- extOptionsPanelBorderSizer.Add(extOptionsPanelSizer, 0, wx.ALL | wx.EXPAND, SPACE)
+ extOptionsPanelSizer.Add(staticBoxSizer, 1, wx.LEFT|wx.EXPAND, SPACE)
+
+ extOptionsPanelBorderSizer.Add(extOptionsPanelSizer, 1, wx.ALL|wx.EXPAND, SPACE)
self.SetSizer(extOptionsPanelBorderSizer)
- self.Layout()
- parent.AddPage(self, _("Extensions"))
-
+
if self.PopulateItems():
self._extListBox.SetSelection(0)
- self.OnListBoxSelect(None)
+ self.OnListBoxSelect()
+
+ self.Layout()
+
+ parent.AddPage(self, _("External Tools"))
def OnOK(self, optionsDialog):
self.SaveCurrentItem()
extensionsService = wx.GetApp().GetService(ExtensionService)
- oldExtensions = extensionsService.GetExtensions()
extensionsService.SetExtensions(self._extensions)
extensionsService.SaveExtensions()
- if oldExtensions.__repr__() != self._extensions.__repr__():
+ if extensionsService.CheckSumExtensions() != self._oldExtensions: # see PopulateItems() note about self._oldExtensions
msgTitle = wx.GetApp().GetAppName()
if not msgTitle:
msgTitle = _("Document Options")
msgTitle,
wx.OK | wx.ICON_INFORMATION,
self.GetParent())
-
+
def PopulateItems(self):
extensionsService = wx.GetApp().GetService(ExtensionService)
import copy
self._extensions = copy.deepcopy(extensionsService.GetExtensions())
+ self._oldExtensions = extensionsService.CheckSumExtensions() # wxBug: need to make a copy now since the deepcopy reorders fields, so we must compare the prestine copy with the modified copy
for extension in self._extensions:
self._extListBox.Append(extension.menuItemName, extension)
self._currentItem = None
self._currentItemIndex = -1
return len(self._extensions)
-
- def OnListBoxSelect(self, event):
+
+ def OnListBoxSelect(self, event=None):
self.SaveCurrentItem()
- if not self._extListBox.GetSelections():
+ if self._extListBox.GetSelection() == wx.NOT_FOUND:
self._currentItemIndex = -1
self._currentItem = None
self._deleteButton.Enable(False)
extension.fileExt = None
else:
extension.fileExt = fileExt.split(',')
-
+ extension.opOnSelectedFile = self._selFileCtrl.GetValue()
+
def LoadItem(self, extension):
if extension:
self._menuItemDescTextCtrl.SetValue(extension.menuItemDesc or '')
self._commandTextCtrl.SetValue(extension.command or '')
+ self._commandTextCtrl.SetToolTipString(extension.command or '')
self._commandPreArgsTextCtrl.SetValue(extension.commandPreArgs or '')
self._commandPostArgsTextCtrl.SetValue(extension.commandPostArgs or '')
if extension.fileExt:
- self._fileExtTextCtrl.SetValue(extension.fileExt.__repr__()[1:-1].replace("'","")) # Make the list a string, strip the brakcet on either side
+ list = ""
+ for ext in extension.fileExt:
+ if list:
+ list = list + ", "
+ list = list + ext
+ self._fileExtTextCtrl.SetValue(list)
else:
self._fileExtTextCtrl.SetValue('')
+ self._selFileCtrl.SetValue(extension.opOnSelectedFile)
self._menuItemNameTextCtrl.SetValue(extension.menuItemName or '') # Do the name last since it triggers the write event that updates the entire item
self._extDetailPanel.Enable()
else:
self._menuItemNameTextCtrl.SetValue('')
self._menuItemDescTextCtrl.SetValue('')
self._commandTextCtrl.SetValue('')
+ self._commandTextCtrl.SetToolTipString(_("Path to executable"))
self._commandPreArgsTextCtrl.SetValue('')
self._commandPostArgsTextCtrl.SetValue('')
self._fileExtTextCtrl.SetValue('')
+ self._selFileCtrl.SetValue(True)
self._extDetailPanel.Enable(False)
-
-
+
+
def OnAdd(self, event):
self.SaveCurrentItem()
- extensionNames = map(lambda extension: extension.menuItemName, self._extensions)
name = _("Untitled")
count = 1
- while name in extensionNames:
+ while self._extListBox.FindString(name) != wx.NOT_FOUND:
count = count + 1
- name = _("Untitled %s") % count
+ name = _("Untitled%s") % count
extension = Extension(name)
self._extensions.append(extension)
self._extListBox.Append(extension.menuItemName, extension)
- self._extListBox.SetSelection(self._extListBox.GetCount() - 1)
- self.OnListBoxSelect(None)
+ self._extListBox.SetStringSelection(extension.menuItemName)
+ self.OnListBoxSelect()
self._menuItemNameTextCtrl.SetFocus()
self._menuItemNameTextCtrl.SetSelection(-1, -1)
-
+
def OnDelete(self, event):
self._extListBox.Delete(self._currentItemIndex)
- self._extensions.remove(self._currentItem)
+ self._extensions.remove(self._currentItem)
self._currentItemIndex = min(self._currentItemIndex, self._extListBox.GetCount() - 1)
if self._currentItemIndex > -1:
self._extListBox.SetSelection(self._currentItemIndex)
self._currentItem = None # Don't update it since it no longer exists
- self.OnListBoxSelect(None)
+ self.OnListBoxSelect()
def OnMoveUp(self, event):
self._extListBox.Insert(itemAboveString, self._currentItemIndex)
self._extListBox.SetClientData(self._currentItemIndex, itemAboveData)
self._currentItemIndex = self._currentItemIndex - 1
- self.OnListBoxSelect(None) # Reset buttons
+ self.OnListBoxSelect() # Reset buttons
def OnMoveDown(self, event):
self._extListBox.Insert(itemBelowString, self._currentItemIndex)
self._extListBox.SetClientData(self._currentItemIndex, itemBelowData)
self._currentItemIndex = self._currentItemIndex + 1
- self.OnListBoxSelect(None) # Reset buttons
+ self.OnListBoxSelect() # Reset buttons