]> git.saurik.com Git - wxWidgets.git/blobdiff - wxPython/samples/ide/activegrid/tool/ExtensionService.py
More bakfile changes needed for bmpcbox. Rebaked.
[wxWidgets.git] / wxPython / samples / ide / activegrid / tool / ExtensionService.py
index b75e544585b3ef75e00400c16893b457c4b4b2ce..535c46eee898ddd926c0ef07ce1b3b006dfaa2a5 100644 (file)
@@ -6,39 +6,35 @@
 #
 # 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 = ''
@@ -46,32 +42,51 @@ class Extension:
         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):
@@ -82,16 +97,20 @@ class ExtensionService(wx.lib.pydocview.DocService):
         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()
@@ -100,8 +119,15 @@ class ExtensionService(wx.lib.pydocview.DocService):
                 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()
@@ -126,6 +152,14 @@ class ExtensionService(wx.lib.pydocview.DocService):
                             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
@@ -136,7 +170,12 @@ class ExtensionService(wx.lib.pydocview.DocService):
             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:
@@ -148,7 +187,7 @@ class ExtensionService(wx.lib.pydocview.DocService):
             if extension.commandPostArgs:
                 cmds.append(extension.commandPostArgs)
             os.spawnv(os.P_NOWAIT, extension.command, cmds)
-                      
+
         else:
             cmd = extension.command
             if extension.commandPreArgs:
@@ -163,107 +202,115 @@ class ExtensionService(wx.lib.pydocview.DocService):
                 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")
@@ -271,22 +318,23 @@ class ExtensionOptionsPanel(wx.Panel):
                           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)
@@ -316,55 +364,64 @@ class ExtensionOptionsPanel(wx.Panel):
                 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):
@@ -374,7 +431,7 @@ class ExtensionOptionsPanel(wx.Panel):
         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):
@@ -384,4 +441,4 @@ class ExtensionOptionsPanel(wx.Panel):
         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