]> git.saurik.com Git - wxWidgets.git/blame - wxPython/samples/ide/activegrid/tool/ExtensionService.py
Docview and IDE patch from Morag Hua with fix for bug #1217890
[wxWidgets.git] / wxPython / samples / ide / activegrid / tool / ExtensionService.py
CommitLineData
2eeaec19
RD
1#----------------------------------------------------------------------------
2# Name: ExtensionService.py
3# Purpose: Extension Service for IDE
4#
5# Author: Peter Yared
6#
7# Created: 5/23/05
8# CVS-ID: $ID:$
9# Copyright: (c) 2005 ActiveGrid, Inc.
10# License: wxWindows License
11#----------------------------------------------------------------------------
12
13import wx
14import wx.lib.pydocview
15import MessageService
16import os
17import os.path
18import pickle
19
20_ = wx.GetTranslation
21
22
23SPACE = 10
24HALF_SPACE = 5
25
26
27EXTENSIONS_CONFIG_STRING = "Extensions"
28
29
30
31# TODO: Redo extensions menu on OK, or provide alert that it won't happen until restart
32
33
34#----------------------------------------------------------------------------
35# Classes
36#----------------------------------------------------------------------------
37
38class Extension:
39
40
41 def __init__(self, menuItemName):
42 self.menuItemName = menuItemName
43 self.id = 0
44 self.menuItemDesc = ''
45 self.command = ''
46 self.commandPreArgs = ''
47 self.commandPostArgs = ''
48 self.fileExt = None
49
50
51class ExtensionService(wx.lib.pydocview.DocService):
52
53
54 def __init__(self):
55 self.LoadExtensions()
56
57
58 def LoadExtensions(self):
59 config = wx.ConfigBase_Get()
60 pickledExtensions = config.Read(EXTENSIONS_CONFIG_STRING)
61 if pickledExtensions:
62 try:
63 self._extensions = pickle.loads(pickledExtensions.encode('ascii'))
64 except:
65 tp, val, tb = sys.exc_info()
66 traceback.print_exception(tp,val,tb)
67 self._extensions = []
68 else:
69 self._extensions = []
70
71
72 def SaveExtensions(self):
73 config = wx.ConfigBase_Get()
74 config.Write(EXTENSIONS_CONFIG_STRING, pickle.dumps(self._extensions))
75
76
77 def GetExtensions(self):
78 return self._extensions
79
80
81 def SetExtensions(self, extensions):
82 self._extensions = extensions
83
84
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)
89 else:
90 toolsMenu = wx.Menu()
91
92 if self._extensions:
93 if toolsMenu.GetMenuItems():
94 toolsMenu.AppendSeparator()
95 for ext in self._extensions:
96 # Append a tool menu item for each extension
97 ext.id = wx.NewId()
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)
101
102 if toolsMenuIndex == -1:
103 formatMenuIndex = menuBar.FindMenu(_("&Format"))
104 menuBar.Insert(formatMenuIndex + 1, toolsMenu, _("&Tools"))
105
106 def ProcessEvent(self, event):
107 id = event.GetId()
108 for extension in self._extensions:
109 if id == extension.id:
110 self.OnExecuteExtension(extension)
111 return True
112 return False
113
114
115 def ProcessUpdateUIEvent(self, event):
116 id = event.GetId()
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:
122 event.Enable(True)
123 return True
124 if doc:
125 for fileExt in extension.fileExt:
126 if fileExt in doc.GetDocumentTemplate().GetFileFilter():
127 event.Enable(True)
128 return True
129 event.Enable(False)
130 return False
131 return False
132
133
134 def OnExecuteExtension(self, extension):
135 if extension.fileExt:
136 doc = wx.GetApp().GetDocumentManager().GetCurrentDocument()
137 if not doc:
138 return
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:
143 return
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)
151
152 else:
153 cmd = extension.command
154 if extension.commandPreArgs:
155 cmd = cmd + ' ' + extension.commandPreArgs
156 if extension.commandPostArgs:
157 cmd = cmd + ' ' + extension.commandPostArgs
158 f = os.popen(cmd)
159 messageService = wx.GetApp().GetService(MessageService.MessageService)
160 messageService.ShowWindow()
161 view = messageService.GetView()
162 for line in f.readlines():
163 view.AddLines(line)
164 view.GetControl().EnsureCaretVisible()
165 f.close()
166
167
168class ExtensionOptionsPanel(wx.Panel):
169
170
171 def __init__(self, parent, id):
172 wx.Panel.__init__(self, parent, id)
173
174 extOptionsPanelBorderSizer = wx.BoxSizer(wx.HORIZONTAL)
175
176 extOptionsPanelSizer = wx.FlexGridSizer(cols=2, hgap=SPACE, vgap=HALF_SPACE)
177
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)
200
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)
207
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)
212
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)
216
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()
223 if path:
224 fileDlg.SetPath(path)
225 if fileDlg.ShowModal() == wx.ID_OK:
226 self._commandTextCtrl.SetValue(fileDlg.GetPath())
227 self._commandTextCtrl.SetInsertionPointEnd()
228 fileDlg.Destroy()
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)
234
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)
238
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)
242
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)
247
248 extOptionsPanelSizer.Add(self._extDetailPanel, 0)
249
250 extOptionsPanelBorderSizer.Add(extOptionsPanelSizer, 0, wx.ALL | wx.EXPAND, SPACE)
251 self.SetSizer(extOptionsPanelBorderSizer)
252 self.Layout()
253 parent.AddPage(self, _("Extensions"))
254
255 if self.PopulateItems():
256 self._extListBox.SetSelection(0)
257 self.OnListBoxSelect(None)
258
259
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()
268 if not msgTitle:
269 msgTitle = _("Document Options")
270 wx.MessageBox(_("Extension changes will not appear until the application is restarted."),
271 msgTitle,
272 wx.OK | wx.ICON_INFORMATION,
273 self.GetParent())
274
275
276 def PopulateItems(self):
277 extensionsService = wx.GetApp().GetService(ExtensionService)
278 import copy
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)
285
286
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)
295 else:
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)
302
303
304 def SaveCurrentItem(self, event=None):
305 extension = self._currentItem
306 if extension:
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(' ','')
315 if not fileExt:
316 extension.fileExt = None
317 else:
318 extension.fileExt = fileExt.split(',')
319
320
321 def LoadItem(self, extension):
322 if 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
329 else:
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()
333 else:
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)
341
342
343 def OnAdd(self, event):
344 self.SaveCurrentItem()
345 extensionNames = map(lambda extension: extension.menuItemName, self._extensions)
346 name = _("Untitled")
347 count = 1
348 while name in extensionNames:
349 count = count + 1
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)
358
359
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)
368
369
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
378
379
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