2 @package modules.extensions
4 @brief GRASS Addons extensions management classes
7 - extensions::InstallExtensionWindow
8 - extensions::ExtensionTree
9 - extensions::UninstallExtensionWindow
10 - extensions::CheckListExtension
12 (C) 2008-2011 by the GRASS Development Team
14 This program is free software under the GNU General Public License
15 (>=v2). Read the file COPYING that comes with GRASS for details.
17 @author Martin Landa <landa.martin gmail.com>
24 import wx.lib.mixins.listctrl
as listmix
26 import wx.lib.agw.customtreectrl
as CT
28 import wx.lib.customtreectrl
as CT
29 import wx.lib.flatnotebook
as FN
34 from core
import globalvar
37 from gui_core.forms
import GUI
42 def __init__(self, parent, id = wx.ID_ANY,
43 title = _(
"Fetch & install extension from GRASS Addons"), **kwargs):
47 wx.Frame.__init__(self, parent = parent, id = id, title = title, **kwargs)
48 self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR,
'grass.ico'), wx.BITMAP_TYPE_ICO))
50 self.
panel = wx.Panel(parent = self, id = wx.ID_ANY)
53 label =
" %s " % _(
"Repository"))
55 label =
" %s " % _(
"List of extensions"))
57 self.
repo = wx.TextCtrl(parent = self.
panel, id = wx.ID_ANY)
59 label = _(
"Fetch full info including description and keywords"))
60 self.fullDesc.SetValue(
True)
63 self.search.SetSelection(0)
68 label =
" %s " % _(
"Options"))
70 task = gtask.parse_interface(
'g.extension.py')
72 ignoreFlags = [
'l',
'c',
'g',
'a',
'f',
'quiet',
'verbose']
73 if sys.platform ==
'win32':
74 ignoreFlags.append(
'd')
75 ignoreFlags.append(
'i')
77 for f
in task.get_options()[
'flags']:
78 name = f.get(
'name',
'')
79 desc = f.get(
'label',
'')
81 desc = f.get(
'description',
'')
82 if not name
and not desc:
84 if name
in ignoreFlags:
86 self.
options[name] = wx.CheckBox(parent = self.
panel, id = wx.ID_ANY,
88 self.repo.SetValue(task.get_param(value =
'svnurl').get(
'default',
89 'http://svn.osgeo.org/grass/grass-addons'))
95 self.btnFetch.SetToolTipString(_(
"Fetch list of available modules from GRASS Addons SVN repository"))
98 label = _(
"&Install"))
99 self.btnInstall.SetToolTipString(_(
"Install selected add-ons GRASS module"))
100 self.btnInstall.Enable(
False)
102 label = _(
"Command dialog"))
103 self.btnCmd.SetToolTipString(_(
'Open %s dialog') %
'g.extension.py')
106 self.btnFetch.Bind(wx.EVT_BUTTON, self.
OnFetch)
107 self.btnInstall.Bind(wx.EVT_BUTTON, self.
OnInstall)
111 self.search.Bind(wx.EVT_TEXT_ENTER, self.
OnShowItem)
118 sizer = wx.BoxSizer(wx.VERTICAL)
119 repoSizer = wx.StaticBoxSizer(self.
repoBox, wx.VERTICAL)
120 repo1Sizer = wx.BoxSizer(wx.HORIZONTAL)
121 repo1Sizer.Add(item = self.
repo, proportion = 1,
122 flag = wx.ALL | wx.ALIGN_CENTER_VERTICAL, border = 1)
123 repo1Sizer.Add(item = self.
btnFetch, proportion = 0,
124 flag = wx.ALL | wx.ALIGN_CENTER_VERTICAL, border = 1)
125 repoSizer.Add(item = repo1Sizer,
129 findSizer = wx.BoxSizer(wx.HORIZONTAL)
130 findSizer.Add(item = self.
search, proportion = 1)
132 treeSizer = wx.StaticBoxSizer(self.
treeBox, wx.HORIZONTAL)
133 treeSizer.Add(item = self.
tree, proportion = 1,
134 flag = wx.ALL | wx.EXPAND, border = 1)
137 optionSizer = wx.StaticBoxSizer(self.
optionBox, wx.VERTICAL)
138 for key
in self.options.keys():
139 optionSizer.Add(item = self.
options[key], proportion = 0)
141 btnSizer = wx.BoxSizer(wx.HORIZONTAL)
142 btnSizer.Add(item = self.
btnCmd, proportion = 0,
143 flag = wx.RIGHT, border = 5)
144 btnSizer.AddSpacer(10)
145 btnSizer.Add(item = self.
btnClose, proportion = 0,
146 flag = wx.RIGHT, border = 5)
147 btnSizer.Add(item = self.
btnInstall, proportion = 0)
149 sizer.Add(item = repoSizer, proportion = 0,
150 flag = wx.ALL | wx.EXPAND, border = 3)
151 sizer.Add(item = findSizer, proportion = 0,
152 flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
153 sizer.Add(item = treeSizer, proportion = 1,
154 flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
155 sizer.Add(item = optionSizer, proportion = 0,
156 flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
157 sizer.Add(item = btnSizer, proportion = 0,
158 flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
160 self.panel.SetSizer(sizer)
161 sizer.Fit(self.
panel)
166 item = self.tree.GetSelected()
167 if not item
or not item.IsOk():
168 return [
'g.extension.py']
170 name = self.tree.GetItemText(item)
172 GError(_(
"Extension not defined"), parent = self)
175 for key
in self.options.keys():
176 if self.
options[key].IsChecked():
177 flags.append(
'-%s' % key)
179 return [
'g.extension.py'] + flags + [
'extension=' + name,
180 'svnurl=' + self.repo.GetValue().strip()]
183 """!Update statusbar text"""
184 element = self.search.GetSelection()
185 if not self.tree.IsLoaded():
186 self.SetStatusText(_(
"Fetch list of available extensions by clicking on 'Fetch' button"), 0)
189 self.tree.SearchItems(element = element,
190 value = event.GetString())
192 nItems = len(self.tree.itemsMarked)
193 if event.GetString():
194 self.SetStatusText(_(
"%d items match") % nItems, 0)
196 self.SetStatusText(
"", 0)
205 """!Fetch list of available extensions"""
207 self.SetStatusText(_(
"Fetching list of modules from GRASS-Addons SVN (be patient)..."), 0)
208 self.tree.Load(url = self.repo.GetValue().strip(), full = self.fullDesc.IsChecked())
209 self.SetStatusText(
"", 0)
213 item = event.GetItem()
214 data = self.tree.GetPyData(item)
215 if data
and 'command' in data:
219 """!Install selected extension"""
220 log = self.parent.GetLogWindow()
225 if not os.getenv(
'GRASS_ADDON_PATH'):
229 log = self.parent.GetLogWindow()
230 log.GetPrompt().SetFilter(
None)
234 item = event.GetItem()
235 self.tree.itemSelected = item
236 data = self.tree.GetPyData(item)
238 self.SetStatusText(
'', 0)
239 self.btnInstall.Enable(
False)
241 self.SetStatusText(data.get(
'description',
''), 0)
242 self.btnInstall.Enable(
True)
245 """!Show selected item"""
246 self.tree.OnShowItem(event)
247 if self.tree.GetSelected():
248 self.btnInstall.Enable()
250 self.btnInstall.Enable(
False)
253 """!Shows command dialog"""
254 GUI(parent = self).ParseCommand(cmd = self.
_getCmd())
257 """!List of available extensions"""
258 def __init__(self, parent, log, id = wx.ID_ANY,
259 ctstyle = CT.TR_HIDE_ROOT | CT.TR_FULL_ROW_HIGHLIGHT | CT.TR_HAS_BUTTONS |
260 CT.TR_LINES_AT_ROOT | CT.TR_SINGLE,
265 super(ExtensionTree, self).
__init__(parent, id, ctstyle = ctstyle, **kwargs)
270 for prefix
in (
'display',
'database',
271 'general',
'imagery',
272 'misc',
'postscript',
'paint',
273 'raster',
'raster3d',
'sites',
'vector',
'wxGUI',
'other'):
274 self.AppendItem(parentId = self.
root,
278 def _expandPrefix(self, c):
279 name = {
'd' :
'display',
298 def _findItem(self, text):
300 item = self.GetFirstChild(self.
root)[0]
301 while item
and item.IsOk():
302 if text == self.GetItemText(item):
305 item = self.GetNextSibling(item)
309 def Load(self, url, full = False):
310 """!Load list of extensions"""
311 self.DeleteAllItems()
312 self.
root = self.AddRoot(_(
"Menu tree"))
319 ret =
RunCommand(
'g.extension.py', read =
True, parent = self,
321 flags = flags, quiet =
True)
326 for line
in ret.splitlines():
329 key, value = line.split(
'=', 1)
336 prefix, name = value.split(
'.', 1)
340 if prefix
not in mdict:
341 mdict[prefix] = dict()
342 mdict[prefix][name] = dict()
344 mdict[prefix][name][key] = value
347 prefix, name = line.strip().
split(
'.', 1)
355 if prefix
not in mdict:
356 mdict[prefix] = dict()
358 mdict[prefix][name] = {
'command' : prefix +
'.' + name }
360 for prefix
in mdict.keys():
363 names = mdict[prefix].keys()
367 text = prefix +
'.' + name
370 new = self.AppendItem(parentId = item,
373 for key
in mdict[prefix][name].keys():
374 data[key] = mdict[prefix][name][key]
376 self.SetPyData(new, data)
381 """Check if items are loaded"""
385 def __init__(self, parent, id = wx.ID_ANY,
386 title = _(
"Uninstall GRASS Addons extensions"), **kwargs):
389 wx.Frame.__init__(self, parent = parent, id = id, title = title, **kwargs)
390 self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR,
'grass.ico'), wx.BITMAP_TYPE_ICO))
392 self.
panel = wx.Panel(parent = self, id = wx.ID_ANY)
395 label =
" %s " % _(
"List of installed extensions"))
401 label = _(
"&Uninstall"))
402 self.btnUninstall.SetToolTipString(_(
"Uninstall selected AddOns extensions"))
404 label = _(
"Command dialog"))
405 self.btnCmd.SetToolTipString(_(
'Open %s dialog') %
'g.extension')
408 self.btnUninstall.Bind(wx.EVT_BUTTON, self.
OnUninstall)
416 sizer = wx.BoxSizer(wx.VERTICAL)
418 extSizer = wx.StaticBoxSizer(self.
extBox, wx.HORIZONTAL)
419 extSizer.Add(item = self.
extList, proportion = 1,
420 flag = wx.ALL | wx.EXPAND, border = 1)
422 btnSizer = wx.BoxSizer(wx.HORIZONTAL)
423 btnSizer.Add(item = self.
btnCmd, proportion = 0,
424 flag = wx.RIGHT, border = 5)
425 btnSizer.AddSpacer(10)
426 btnSizer.Add(item = self.
btnClose, proportion = 0,
427 flag = wx.RIGHT, border = 5)
430 sizer.Add(item = extSizer, proportion = 1,
431 flag = wx.ALL | wx.EXPAND, border = 3)
432 sizer.Add(item = btnSizer, proportion = 0,
433 flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
435 self.panel.SetSizer(sizer)
436 sizer.Fit(self.
panel)
445 """!Uninstall selected extensions"""
446 log = self.parent.GetLogWindow()
447 eList = self.extList.GetExtensions()
449 GError(_(
"No extension selected for removal. "
450 "Operation canceled."),
455 files =
RunCommand(
'g.extension.py', parent = self, read =
True, quiet =
True,
456 extension = ext, operation =
'remove').splitlines()
457 dlg = wx.MessageDialog(parent = self,
458 message = _(
"List of files to be removed:\n%(files)s\n\n"
459 "Do you want really to remove <%(ext)s> extension?") % \
460 {
'files' : os.linesep.join(files),
'ext' : ext },
461 caption = _(
"Remove extension"),
462 style = wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
464 if dlg.ShowModal() == wx.ID_YES:
465 RunCommand(
'g.extension.py', flags =
'f', parent = self, quiet =
True,
466 extension = ext, operation =
'remove')
468 self.extList.LoadData()
472 log = self.parent.GetLogWindow()
473 log.GetPrompt().SetFilter(
None)
476 """!Shows command dialog"""
477 GUI(parent = self).ParseCommand(cmd = [
'g.extension.py'])
480 """!List of mapset/owner/group"""
484 wx.ListCtrl.__init__(self, parent, id = wx.ID_ANY,
485 style = wx.LC_REPORT)
486 listmix.CheckListCtrlMixin.__init__(self)
489 listmix.ListCtrlAutoWidthMixin.__init__(self)
491 self.InsertColumn(0, _(
'Extension'))
495 """!Load data into list"""
496 self.DeleteAllItems()
498 quiet =
True, parent = self, read =
True,
499 flags =
'a').splitlines():
501 self.InsertStringItem(sys.maxint, ext)
504 """!Get extensions to be un-installed
507 for i
in range(self.GetItemCount()):
508 if self.IsChecked(i):
509 name = self.GetItemText(i)
List of mapset/owner/group.
def Load
Load list of extensions.
def OnShowItem
Show selected item.
def split
Platform spefic shlex.split.
def OnInstall
Install selected extension.
def SetAddOnPath
Set default AddOn path.
def OnUpdateStatusBar
Update statusbar text.
def OnFetch
Fetch list of available extensions.
def OnItemSelected
Item selected.
def OnCloseWindow
Close window.
Misc utilities for wxGUI.
def OnCmdDialog
Shows command dialog.
def OnCloseWindow
Close window.
def LoadData
Load data into list.
def UpdateGRASSAddOnCommands
Update list of available GRASS AddOns commands to use when parsing string from the command line...
def OnCmdDialog
Shows command dialog.
def GetExtensions
Get extensions to be un-installed.
def RunCommand
Run GRASS command.
List of available extensions.
def OnUninstall
Uninstall selected extensions.