12 - InstallExtensionWindow
14 - UninstallExtensionWindow
20 (C) 2008-2011 by the GRASS Development Team
21 This program is free software under the GNU General Public License
22 (>=v2). Read the file COPYING that comes with GRASS for details.
24 @author Martin Landa <landa.martin gmail.com>
32 import wx.lib.mixins.listctrl
as listmix
34 import wx.lib.agw.customtreectrl
as CT
37 import wx.lib.customtreectrl
as CT
39 import wx.lib.flatnotebook
as FN
40 import wx.lib.scrolledpanel
as scrolled
53 """!GRASS Quickstart help window"""
54 def __init__(self, parent, id, title, size, file):
55 wx.Frame.__init__(self, parent = parent, id = id, title = title, size = size)
57 sizer = wx.BoxSizer(wx.VERTICAL)
61 content.LoadPage(file)
63 sizer.Add(item = content, proportion = 1, flag = wx.EXPAND)
65 self.SetAutoLayout(
True)
70 """!Search module window (used in MenuTreeWindow)"""
71 def __init__(self, parent, id = wx.ID_ANY, cmdPrompt = None,
72 showChoice =
True, showTip =
False, **kwargs):
77 wx.Panel.__init__(self, parent = parent, id = id, **kwargs)
79 self.
_searchDict = { _(
'description') :
'description',
80 _(
'command') :
'command',
81 _(
'keywords') :
'keywords' }
83 self.
box = wx.StaticBox(parent = self, id = wx.ID_ANY,
84 label =
" %s " % _(
"Find module(s)"))
86 self.
searchBy = wx.Choice(parent = self, id = wx.ID_ANY,
87 choices = [_(
'description'),
90 self.searchBy.SetSelection(0)
92 self.
search = wx.TextCtrl(parent = self, id = wx.ID_ANY,
93 value =
"", size = (-1, 25),
94 style = wx.TE_PROCESS_ENTER)
104 self.searchChoice.SetItems(self.cmdPrompt.GetCommandItems())
111 sizer = wx.StaticBoxSizer(self.
box, wx.HORIZONTAL)
112 gridSizer = wx.GridBagSizer(hgap = 3, vgap = 3)
113 gridSizer.AddGrowableCol(1)
116 flag = wx.ALIGN_CENTER_VERTICAL, pos = (0, 0))
117 gridSizer.Add(item = self.
search,
118 flag = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, pos = (0, 1))
122 flag = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, pos = (row, 0), span = (1, 2))
127 flag = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, pos = (row, 0), span = (1, 2))
129 sizer.Add(item = gridSizer, proportion = 1)
135 """!Get selected element"""
136 selection = self.searchBy.GetStringSelection()
141 """!Set selection element"""
142 self.searchBy.SetSelection(i)
145 """!Search module by keywords or description"""
150 text = event.GetString()
152 self.cmdPrompt.SetFilter(
None)
153 mList = self.cmdPrompt.GetCommandItems()
154 self.searchChoice.SetItems(mList)
156 self.searchTip.SetLabel(_(
"%d modules found") % len(mList))
162 for module, data
in self.cmdPrompt.moduleDesc.iteritems():
164 sel = self.searchBy.GetSelection()
166 if text
in data[
'desc']:
169 if text
in ','.join(data[
'keywords']):
172 if module[:len(text)] == text:
178 group, name = module.split(
'.')
182 if group
not in modules:
183 modules[group] = list()
184 modules[group].append(name)
186 self.cmdPrompt.SetFilter(modules)
187 self.searchChoice.SetItems(self.cmdPrompt.GetCommandItems())
189 self.searchTip.SetLabel(_(
"%d modules found") % iFound)
194 """!Module selected from choice, update command prompt"""
195 cmd = event.GetString().
split(
' ', 1)[0]
200 self.cmdPrompt.SetText(text)
201 self.cmdPrompt.SetSelectionStart(pos)
202 self.cmdPrompt.SetCurrentPos(pos)
203 self.cmdPrompt.SetFocus()
205 desc = self.cmdPrompt.GetCommandDesc(cmd)
207 self.searchTip.SetLabel(desc)
211 self.searchBy.SetSelection(0)
212 self.search.SetValue(
'')
214 self.searchTip.SetLabel(
'')
217 """!Show menu tree"""
218 def __init__(self, parent, id = wx.ID_ANY, **kwargs):
221 wx.Panel.__init__(self, parent = parent, id = id, **kwargs)
223 self.
dataBox = wx.StaticBox(parent = self, id = wx.ID_ANY,
224 label =
" %s " % _(
"Menu tree (double-click to run command)"))
233 self.
btnRun = wx.Button(self, id = wx.ID_OK, label = _(
"&Run"))
234 self.btnRun.SetToolTipString(_(
"Run selected command"))
235 self.btnRun.Enable(
False)
238 self.btnRun.Bind(wx.EVT_BUTTON, self.
OnRun)
241 self.search.Bind(wx.EVT_TEXT_ENTER, self.
OnShowItem)
246 self.search.SetFocus()
249 """!Do dialog layout"""
250 sizer = wx.BoxSizer(wx.VERTICAL)
253 dataSizer = wx.StaticBoxSizer(self.
dataBox, wx.HORIZONTAL)
254 dataSizer.Add(item = self.
tree, proportion =1,
258 btnSizer = wx.BoxSizer(wx.HORIZONTAL)
259 btnSizer.Add(item = self.
btnRun, proportion = 0)
261 sizer.Add(item = dataSizer, proportion = 1,
262 flag = wx.EXPAND | wx.ALL, border = 5)
264 sizer.Add(item = self.
search, proportion = 0,
265 flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
267 sizer.Add(item = btnSizer, proportion = 0,
268 flag = wx.ALIGN_RIGHT | wx.BOTTOM | wx.RIGHT, border = 5)
271 sizer.SetSizeHints(self)
276 self.SetAutoLayout(
True)
284 """!Run selected command"""
285 if not self.tree.GetSelected():
288 data = self.tree.GetPyData(self.tree.GetSelected())
292 handler =
'self.parent.' + data[
'handler'].lstrip(
'self.')
293 if data[
'handler'] ==
'self.OnXTerm':
294 wx.MessageBox(parent = self,
295 message = _(
'You must run this command from the menu or command line',
296 'This command require an XTerm'),
297 caption = _(
'Message'), style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
298 elif data[
'command']:
299 eval(handler)(event =
None, cmd = data[
'command'].
split())
304 """!Show selected item"""
305 self.tree.OnShowItem(event)
306 if self.tree.GetSelected():
309 self.btnRun.Enable(
False)
312 """!Item activated (double-click)"""
313 item = event.GetItem()
314 if not item
or not item.IsOk():
317 data = self.tree.GetPyData(item)
318 if not data
or 'command' not in data:
321 self.tree.itemSelected = item
327 item = event.GetItem()
328 if not item
or not item.IsOk():
331 data = self.tree.GetPyData(item)
332 if not data
or 'command' not in data:
336 label = data[
'command'] +
' -- ' + data[
'description']
338 label = data[
'description']
340 self.parent.SetStatusText(label, 0)
343 """!Update statusbar text"""
344 element = self.search.GetSelection()
345 self.tree.SearchItems(element = element,
346 value = event.GetString())
348 nItems = len(self.tree.itemsMarked)
349 if event.GetString():
350 self.parent.SetStatusText(_(
"%d modules match") % nItems, 0)
352 self.parent.SetStatusText(
"", 0)
357 def __init__(self, parent, id = wx.ID_ANY,
358 ctstyle = CT.TR_HIDE_ROOT | CT.TR_FULL_ROW_HIGHLIGHT | CT.TR_HAS_BUTTONS |
359 CT.TR_LINES_AT_ROOT | CT.TR_SINGLE, **kwargs):
361 super(ItemTree, self).
__init__(parent, id, agwStyle = ctstyle, **kwargs)
363 super(ItemTree, self).
__init__(parent, id, style = ctstyle, **kwargs)
365 self.
root = self.AddRoot(_(
"Menu tree"))
372 @param element element index (see self.searchBy)
375 @return list of found tree items
381 item = self.GetFirstChild(self.
root)[0]
389 def _processItem(self, item, element, value, listOfItems):
390 """!Search items (used by SearchItems)
392 @param item reference item
393 @param listOfItems list of found items
395 while item
and item.IsOk():
396 subItem = self.GetFirstChild(item)[0]
399 data = self.GetPyData(item)
401 if data
and element
in data
and \
402 value.lower()
in data[element].lower():
403 listOfItems.append(item)
405 item = self.GetNextSibling(item)
408 """!Get selected item"""
412 """!Highlight first found item in menu tree"""
416 idx = self.itemsMarked.index(self.
GetSelected()) + 1
428 for item
in self.root.GetChildren():
430 itemSelected = self.GetSelection()
432 self.ToggleItemSelection(itemSelected)
436 """!Menu tree class"""
441 super(MenuTree, self).
__init__(parent, **kwargs)
444 """!Load menu data tree
446 @param data menu data (None to use self.menudata)
452 for eachMenuData
in data.GetMenu():
453 for label, items
in eachMenuData:
454 item = self.AppendItem(parentId = self.
root,
455 text = label.replace(
'&',
''))
458 def __AppendItems(self, item, data):
459 """!Append items into tree (used by Load()
461 @param item tree item (parent)
462 @parent data menu data"""
463 for eachItem
in data:
464 if len(eachItem) == 2:
466 itemSub = self.AppendItem(parentId = item,
471 itemNew = self.AppendItem(parentId = item,
474 data = {
'item' : eachItem[0],
475 'description' : eachItem[1],
476 'handler' : eachItem[2],
477 'command' : eachItem[3],
478 'keywords' : eachItem[4] }
480 self.SetPyData(itemNew, data)
483 """!Create custom About Window
485 @todo improve styling
487 def __init__(self, parent, size = (750, 400),
488 title = _(
'About GRASS GIS'), **kwargs):
489 wx.Frame.__init__(self, parent = parent, id = wx.ID_ANY, size = size, **kwargs)
491 panel = wx.Panel(parent = self, id = wx.ID_ANY)
494 self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR,
'grass.ico'), wx.BITMAP_TYPE_ICO))
497 vInfo = grass.version()
499 infoTxt = wx.Panel(parent = panel, id = wx.ID_ANY)
500 infoSizer = wx.BoxSizer(wx.VERTICAL)
501 infoGridSizer = wx.GridBagSizer(vgap = 5, hgap = 5)
502 infoGridSizer.AddGrowableCol(0)
503 infoGridSizer.AddGrowableCol(1)
504 logo = os.path.join(globalvar.ETCDIR,
"gui",
"icons",
"grass.ico")
505 logoBitmap = wx.StaticBitmap(parent = infoTxt, id = wx.ID_ANY,
506 bitmap = wx.Bitmap(name = logo,
507 type = wx.BITMAP_TYPE_ICO))
508 infoSizer.Add(item = logoBitmap, proportion = 0,
509 flag = wx.ALL | wx.ALIGN_CENTER, border = 25)
511 info = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
512 label =
'GRASS GIS ' + vInfo[
'version'] +
'\n\n')
513 info.SetFont(wx.Font(13, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0,
""))
514 infoSizer.Add(item = info, proportion = 0,
515 flag = wx.BOTTOM | wx.ALIGN_CENTER, border = 15)
517 infoGridSizer.Add(item = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
518 label = _(
'Official GRASS site:')),
520 flag = wx.ALIGN_RIGHT)
522 infoGridSizer.Add(item = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
523 label =
'http://grass.osgeo.org'),
525 flag = wx.ALIGN_LEFT)
527 infoGridSizer.Add(item = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
528 label = _(
'SVN Revision:')),
530 flag = wx.ALIGN_RIGHT)
532 infoGridSizer.Add(item = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
533 label = vInfo[
'revision']),
535 flag = wx.ALIGN_LEFT)
537 infoGridSizer.Add(item = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
538 label = _(
'GIS Library Revision:')),
540 flag = wx.ALIGN_RIGHT)
542 infoGridSizer.Add(item = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
543 label = vInfo[
'libgis_revision'] +
' (' +
544 vInfo[
'libgis_date'].
split(
' ')[0] +
')'),
546 flag = wx.ALIGN_LEFT)
548 infoSizer.Add(item = infoGridSizer,
550 flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL,
554 aboutNotebook =
menuform.GNotebook(panel, style = globalvar.FNPageStyle | FN.FNB_NO_X_BUTTON)
555 aboutNotebook.SetTabAreaColour(globalvar.FNPageColor)
557 for title, win
in ((_(
"Info"), infoTxt),
564 aboutNotebook.AddPage(page = win, text = title)
565 wx.CallAfter(aboutNotebook.SetSelection, 0)
568 btnClose = wx.Button(parent = panel, id = wx.ID_CLOSE)
569 btnSizer = wx.BoxSizer(wx.HORIZONTAL)
570 btnSizer.Add(item = btnClose, proportion = 0,
571 flag = wx.ALL | wx.ALIGN_RIGHT,
576 infoTxt.SetSizer(infoSizer)
577 infoSizer.Fit(infoTxt)
579 sizer = wx.BoxSizer(wx.VERTICAL)
580 sizer.Add(item = aboutNotebook, proportion = 1,
581 flag = wx.EXPAND | wx.ALL, border = 1)
582 sizer.Add(item = btnSizer, proportion = 0,
583 flag = wx.ALL | wx.ALIGN_RIGHT, border = 1)
584 panel.SetSizer(sizer)
587 def _pageCopyright(self):
588 """Copyright information"""
589 copyfile = os.path.join(os.getenv(
"GISBASE"),
"COPYING")
590 if os.path.exists(copyfile):
591 copyrightFile = open(copyfile,
'r')
592 copytext = copyrightFile.read()
593 copyrightFile.close()
595 copytext = _(
'%s file missing') %
'COPYING'
598 copyrightwin = scrolled.ScrolledPanel(self, id = wx.ID_ANY,
599 size = wx.DefaultSize,
600 style = wx.TAB_TRAVERSAL | wx.SUNKEN_BORDER)
601 copyrighttxt = wx.StaticText(copyrightwin, id = wx.ID_ANY, label = copytext)
602 copyrightwin.SetAutoLayout(
True)
603 copyrightwin.sizer = wx.BoxSizer(wx.VERTICAL)
604 copyrightwin.sizer.Add(item = copyrighttxt, proportion = 1,
605 flag = wx.EXPAND | wx.ALL, border = 3)
606 copyrightwin.SetSizer(copyrightwin.sizer)
607 copyrightwin.Layout()
608 copyrightwin.SetupScrolling()
612 def _pageLicense(self):
614 licfile = os.path.join(os.getenv(
"GISBASE"),
"GPL.TXT")
615 if os.path.exists(licfile):
616 licenceFile = open(licfile,
'r')
617 license = ''.join(licenceFile.readlines())
620 license = _(
'%s file missing') %
'GPL.TXT'
622 licensewin = scrolled.ScrolledPanel(self, id = wx.ID_ANY,
623 style = wx.TAB_TRAVERSAL | wx.SUNKEN_BORDER)
624 licensetxt = wx.StaticText(licensewin, id = wx.ID_ANY, label = license)
625 licensewin.SetAutoLayout(
True)
626 licensewin.sizer = wx.BoxSizer(wx.VERTICAL)
627 licensewin.sizer.Add(item = licensetxt, proportion = 1,
628 flag = wx.EXPAND | wx.ALL, border = 3)
629 licensewin.SetSizer(licensewin.sizer)
631 licensewin.SetupScrolling()
635 def _pageCredit(self):
638 authfile = os.path.join(os.getenv(
"GISBASE"),
"AUTHORS")
639 if os.path.exists(authfile):
640 authorsFile = open(authfile,
'r')
641 authors = unicode(''.join(authorsFile.readlines()),
"utf-8")
644 authors = _(
'%s file missing') %
'AUTHORS'
645 authorwin = scrolled.ScrolledPanel(self, id = wx.ID_ANY,
646 style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
647 authortxt = wx.StaticText(authorwin, id = wx.ID_ANY, label = authors)
648 authorwin.SetAutoLayout(1)
649 authorwin.SetupScrolling()
650 authorwin.sizer = wx.BoxSizer(wx.VERTICAL)
651 authorwin.sizer.Add(item = authortxt, proportion = 1,
652 flag = wx.EXPAND | wx.ALL, border = 3)
653 authorwin.SetSizer(authorwin.sizer)
658 def _pageContributors(self, extra = False):
659 """Contributors info"""
661 contribfile = os.path.join(os.getenv(
"GISBASE"),
"contributors_extra.csv")
663 contribfile = os.path.join(os.getenv(
"GISBASE"),
"contributors.csv")
664 if os.path.exists(contribfile):
665 contribFile = codecs.open(contribfile, encoding =
'utf-8', mode =
'r')
668 for line
in contribFile.readlines()[1:]:
669 line = line.rstrip(
'\n')
672 name, email, rfc2_agreed = line.split(
',')
674 cvs_id, name, email, country, osgeo_id, rfc2_agreed = line.split(
',')
676 errLines.append(line)
679 contribs.append((name, email))
681 contribs.append((name, email, country, osgeo_id))
687 message = _(
"Error when reading file '%s'.") % contribfile + \
688 "\n\n" + _(
"Lines:") +
" %s" % \
689 os.linesep.join(
map(utils.UnicodeString, errLines)))
693 contribwin = scrolled.ScrolledPanel(self, id = wx.ID_ANY,
694 style = wx.TAB_TRAVERSAL | wx.SUNKEN_BORDER)
695 contribwin.SetAutoLayout(
True)
696 contribwin.SetupScrolling()
697 contribwin.sizer = wx.BoxSizer(wx.VERTICAL)
700 contribtxt = wx.StaticText(contribwin, id = wx.ID_ANY,
701 label = _(
'%s file missing') % contribfile)
702 contribwin.sizer.Add(item = contribtxt, proportion = 1,
703 flag = wx.EXPAND | wx.ALL, border = 3)
706 items = (_(
'Name'), _(
'E-mail'))
708 items = (_(
'Name'), _(
'E-mail'), _(
'Country'), _(
'OSGeo_ID'))
709 contribBox = wx.FlexGridSizer(cols = len(items), vgap = 5, hgap = 5)
711 contribBox.Add(item = wx.StaticText(parent = contribwin, id = wx.ID_ANY,
713 for vals
in contribs:
715 contribBox.Add(item = wx.StaticText(parent = contribwin, id = wx.ID_ANY,
717 contribwin.sizer.Add(item = contribBox, proportion = 1,
718 flag = wx.EXPAND | wx.ALL, border = 3)
720 contribwin.SetSizer(contribwin.sizer)
725 def _pageTranslators(self):
726 """Translators info"""
727 translatorsfile = os.path.join(os.getenv(
"GISBASE"),
"translators.csv")
728 if os.path.exists(translatorsfile):
729 translatorsFile = open(translatorsfile,
'r')
732 for line
in translatorsFile.readlines()[1:]:
733 line = line.rstrip(
'\n')
735 name, email, languages = line.split(
',')
737 errLines.append(line)
739 for language
in languages.split(
' '):
740 if language
not in translators:
741 translators[language] = list()
742 translators[language].append((name, email))
743 translatorsFile.close()
747 message = _(
"Error when reading file '%s'.") % translatorsfile + \
748 "\n\n" + _(
"Lines:") +
" %s" % \
749 os.linesep.join(
map(utils.UnicodeString, errLines)))
753 translatorswin = scrolled.ScrolledPanel(self, id = wx.ID_ANY,
754 style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
755 translatorswin.SetAutoLayout(1)
756 translatorswin.SetupScrolling()
757 translatorswin.sizer = wx.BoxSizer(wx.VERTICAL)
760 translatorstxt = wx.StaticText(translatorswin, id = wx.ID_ANY,
761 label = _(
'%s file missing') %
'translators.csv')
762 translatorswin.sizer.Add(item = translatorstxt, proportion = 1,
763 flag = wx.EXPAND | wx.ALL, border = 3)
765 translatorsBox = wx.FlexGridSizer(cols = 3, vgap = 5, hgap = 5)
766 languages = translators.keys()
768 translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
770 translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
771 label = _(
'E-mail')))
772 translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
773 label = _(
'Language')))
774 for lang
in languages:
775 for translator
in translators[lang]:
776 name, email = translator
777 translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
778 label = unicode(name,
"utf-8")))
779 translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
781 translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
784 translatorswin.sizer.Add(item = translatorsBox, proportion = 1,
785 flag = wx.EXPAND | wx.ALL, border = 3)
787 translatorswin.SetSizer(translatorswin.sizer)
788 translatorswin.Layout()
790 return translatorswin
797 def __init__(self, parent, id = wx.ID_ANY,
798 title = _(
"Fetch & install extension from GRASS Addons"), **kwargs):
802 wx.Frame.__init__(self, parent = parent, id = id, title = title, **kwargs)
803 self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR,
'grass.ico'), wx.BITMAP_TYPE_ICO))
805 self.
panel = wx.Panel(parent = self, id = wx.ID_ANY)
808 label =
" %s " % _(
"Repository"))
810 label =
" %s " % _(
"List of extensions"))
812 self.
repo = wx.TextCtrl(parent = self.
panel, id = wx.ID_ANY)
814 label = _(
"Fetch full info including description and keywords"))
815 self.fullDesc.SetValue(
True)
818 self.search.SetSelection(0)
823 label =
" %s " % _(
"Options"))
825 task = gtask.parse_interface(
'g.extension.py')
827 ignoreFlags = [
'l',
'c',
'g',
'a',
'f',
'quiet',
'verbose']
828 if sys.platform ==
'win32':
829 ignoreFlags.append(
'd')
830 ignoreFlags.append(
'i')
832 for f
in task.get_options()[
'flags']:
833 name = f.get(
'name',
'')
834 desc = f.get(
'label',
'')
836 desc = f.get(
'description',
'')
837 if not name
and not desc:
839 if name
in ignoreFlags:
841 self.
options[name] = wx.CheckBox(parent = self.
panel, id = wx.ID_ANY,
843 self.repo.SetValue(task.get_param(value =
'svnurl').get(
'default',
844 'http://svn.osgeo.org/grass/grass-addons'))
850 self.btnFetch.SetToolTipString(_(
"Fetch list of available modules from GRASS Addons SVN repository"))
853 label = _(
"&Install"))
854 self.btnInstall.SetToolTipString(_(
"Install selected add-ons GRASS module"))
855 self.btnInstall.Enable(
False)
857 label = _(
"Command dialog"))
858 self.btnCmd.SetToolTipString(_(
'Open %s dialog') %
'g.extension.py')
861 self.btnFetch.Bind(wx.EVT_BUTTON, self.
OnFetch)
862 self.btnInstall.Bind(wx.EVT_BUTTON, self.
OnInstall)
866 self.search.Bind(wx.EVT_TEXT_ENTER, self.
OnShowItem)
873 sizer = wx.BoxSizer(wx.VERTICAL)
874 repoSizer = wx.StaticBoxSizer(self.
repoBox, wx.VERTICAL)
875 repo1Sizer = wx.BoxSizer(wx.HORIZONTAL)
876 repo1Sizer.Add(item = self.
repo, proportion = 1,
877 flag = wx.ALL | wx.ALIGN_CENTER_VERTICAL, border = 1)
878 repo1Sizer.Add(item = self.
btnFetch, proportion = 0,
879 flag = wx.ALL | wx.ALIGN_CENTER_VERTICAL, border = 1)
880 repoSizer.Add(item = repo1Sizer,
884 findSizer = wx.BoxSizer(wx.HORIZONTAL)
885 findSizer.Add(item = self.
search, proportion = 1)
887 treeSizer = wx.StaticBoxSizer(self.
treeBox, wx.HORIZONTAL)
888 treeSizer.Add(item = self.
tree, proportion = 1,
889 flag = wx.ALL | wx.EXPAND, border = 1)
892 optionSizer = wx.StaticBoxSizer(self.
optionBox, wx.VERTICAL)
893 for key
in self.options.keys():
894 optionSizer.Add(item = self.
options[key], proportion = 0)
896 btnSizer = wx.BoxSizer(wx.HORIZONTAL)
897 btnSizer.Add(item = self.
btnCmd, proportion = 0,
898 flag = wx.RIGHT, border = 5)
899 btnSizer.AddSpacer(10)
900 btnSizer.Add(item = self.
btnClose, proportion = 0,
901 flag = wx.RIGHT, border = 5)
902 btnSizer.Add(item = self.
btnInstall, proportion = 0)
904 sizer.Add(item = repoSizer, proportion = 0,
905 flag = wx.ALL | wx.EXPAND, border = 3)
906 sizer.Add(item = findSizer, proportion = 0,
907 flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
908 sizer.Add(item = treeSizer, proportion = 1,
909 flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
910 sizer.Add(item = optionSizer, proportion = 0,
911 flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
912 sizer.Add(item = btnSizer, proportion = 0,
913 flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
915 self.panel.SetSizer(sizer)
916 sizer.Fit(self.
panel)
921 item = self.tree.GetSelected()
922 if not item
or not item.IsOk():
923 return [
'g.extension.py']
925 name = self.tree.GetItemText(item)
927 gcmd.GError(_(
"Extension not defined"), parent = self)
930 for key
in self.options.keys():
931 if self.
options[key].IsChecked():
932 flags.append(
'-%s' % key)
934 return [
'g.extension.py'] + flags + [
'extension=' + name,
935 'svnurl=' + self.repo.GetValue().strip()]
938 """!Update statusbar text"""
939 element = self.search.GetSelection()
940 if not self.tree.IsLoaded():
941 self.SetStatusText(_(
"Fetch list of available extensions by clicking on 'Fetch' button"), 0)
944 self.tree.SearchItems(element = element,
945 value = event.GetString())
947 nItems = len(self.tree.itemsMarked)
948 if event.GetString():
949 self.SetStatusText(_(
"%d items match") % nItems, 0)
951 self.SetStatusText(
"", 0)
960 """!Fetch list of available extensions"""
962 self.SetStatusText(_(
"Fetching list of modules from GRASS-Addons SVN (be patient)..."), 0)
963 self.tree.Load(url = self.repo.GetValue().strip(), full = self.fullDesc.IsChecked())
964 self.SetStatusText(
"", 0)
968 item = event.GetItem()
969 data = self.tree.GetPyData(item)
970 if data
and 'command' in data:
974 """!Install selected extension"""
975 log = self.parent.GetLogWindow()
979 item = self.tree.GetSelected()
980 if not item
or not item.IsOk()
or \
982 not os.getenv(
'GRASS_ADDON_PATH'):
985 name = self.tree.GetItemText(item)
986 globalvar.grassCmd[
'all'].append(name)
990 item = event.GetItem()
991 self.tree.itemSelected = item
992 data = self.tree.GetPyData(item)
994 self.SetStatusText(
'', 0)
995 self.btnInstall.Enable(
False)
997 self.SetStatusText(data.get(
'description',
''), 0)
998 self.btnInstall.Enable(
True)
1001 """!Show selected item"""
1002 self.tree.OnShowItem(event)
1003 if self.tree.GetSelected():
1004 self.btnInstall.Enable()
1006 self.btnInstall.Enable(
False)
1009 """!Shows command dialog"""
1013 """!List of available extensions"""
1014 def __init__(self, parent, log, id = wx.ID_ANY,
1015 ctstyle = CT.TR_HIDE_ROOT | CT.TR_FULL_ROW_HIGHLIGHT | CT.TR_HAS_BUTTONS |
1016 CT.TR_LINES_AT_ROOT | CT.TR_SINGLE,
1021 super(ExtensionTree, self).
__init__(parent, id, ctstyle = ctstyle, **kwargs)
1025 def _initTree(self):
1026 for prefix
in (
'display',
'database',
1027 'general',
'imagery',
1028 'misc',
'postscript',
'paint',
1029 'raster',
'raster3d',
'sites',
'vector',
'wxGUI',
'other'):
1030 self.AppendItem(parentId = self.
root,
1034 def _expandPrefix(self, c):
1035 name = {
'd' :
'display',
1040 'ps' :
'postscript',
1054 def _findItem(self, text):
1056 item = self.GetFirstChild(self.
root)[0]
1057 while item
and item.IsOk():
1058 if text == self.GetItemText(item):
1061 item = self.GetNextSibling(item)
1066 """!Load list of extensions"""
1067 self.DeleteAllItems()
1068 self.
root = self.AddRoot(_(
"Menu tree"))
1075 ret = gcmd.RunCommand(
'g.extension.py', read =
True, parent = self,
1077 flags = flags, quiet =
True)
1082 for line
in ret.splitlines():
1085 key, value = line.split(
'=', 1)
1092 prefix, name = value.split(
'.', 1)
1096 if prefix
not in mdict:
1097 mdict[prefix] = dict()
1098 mdict[prefix][name] = dict()
1100 mdict[prefix][name][key] = value
1103 prefix, name = line.strip().
split(
'.', 1)
1111 if prefix
not in mdict:
1112 mdict[prefix] = dict()
1114 mdict[prefix][name] = {
'command' : prefix +
'.' + name }
1116 for prefix
in mdict.keys():
1119 names = mdict[prefix].keys()
1123 text = prefix +
'.' + name
1126 new = self.AppendItem(parentId = item,
1129 for key
in mdict[prefix][name].keys():
1130 data[key] = mdict[prefix][name][key]
1132 self.SetPyData(new, data)
1137 """Check if items are loaded"""
1141 def __init__(self, parent, id = wx.ID_ANY,
1142 title = _(
"Uninstall GRASS Addons extensions"), **kwargs):
1145 wx.Frame.__init__(self, parent = parent, id = id, title = title, **kwargs)
1146 self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR,
'grass.ico'), wx.BITMAP_TYPE_ICO))
1148 self.
panel = wx.Panel(parent = self, id = wx.ID_ANY)
1151 label =
" %s " % _(
"List of installed extensions"))
1157 label = _(
"&Uninstall"))
1158 self.btnUninstall.SetToolTipString(_(
"Uninstall selected AddOns extensions"))
1160 label = _(
"Command dialog"))
1161 self.btnCmd.SetToolTipString(_(
'Open %s dialog') %
'g.extension')
1164 self.btnUninstall.Bind(wx.EVT_BUTTON, self.
OnUninstall)
1172 sizer = wx.BoxSizer(wx.VERTICAL)
1174 extSizer = wx.StaticBoxSizer(self.
extBox, wx.HORIZONTAL)
1175 extSizer.Add(item = self.
extList, proportion = 1,
1176 flag = wx.ALL | wx.EXPAND, border = 1)
1178 btnSizer = wx.BoxSizer(wx.HORIZONTAL)
1179 btnSizer.Add(item = self.
btnCmd, proportion = 0,
1180 flag = wx.RIGHT, border = 5)
1181 btnSizer.AddSpacer(10)
1182 btnSizer.Add(item = self.
btnClose, proportion = 0,
1183 flag = wx.RIGHT, border = 5)
1186 sizer.Add(item = extSizer, proportion = 1,
1187 flag = wx.ALL | wx.EXPAND, border = 3)
1188 sizer.Add(item = btnSizer, proportion = 0,
1189 flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
1191 self.panel.SetSizer(sizer)
1192 sizer.Fit(self.
panel)
1201 """!Uninstall selected extensions"""
1202 log = self.parent.GetLogWindow()
1203 eList = self.extList.GetExtensions()
1205 gcmd.GError(_(
"No extension selected for removal. "
1206 "Operation canceled."),
1211 files = gcmd.RunCommand(
'g.extension.py', parent = self, read =
True, quiet =
True,
1212 extension = ext, operation =
'remove').splitlines()
1213 dlg = wx.MessageDialog(parent = self,
1214 message = _(
"List of files to be removed:\n%(files)s\n\n"
1215 "Do you want really to remove <%(ext)s> extension?") % \
1216 {
'files' : os.linesep.join(files),
'ext' : ext },
1217 caption = _(
"Remove extension"),
1218 style = wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
1220 if dlg.ShowModal() == wx.ID_YES:
1221 gcmd.RunCommand(
'g.extension.py', flags =
'f', parent = self, quiet =
True,
1222 extension = ext, operation =
'remove')
1224 self.extList.LoadData()
1227 """!Shows command dialog"""
1228 menuform.GUI(parent = self).ParseCommand(cmd = [
'g.extension.py'])
1231 """!List of mapset/owner/group"""
1235 wx.ListCtrl.__init__(self, parent, id = wx.ID_ANY,
1236 style = wx.LC_REPORT)
1237 listmix.CheckListCtrlMixin.__init__(self)
1240 listmix.ListCtrlAutoWidthMixin.__init__(self)
1242 self.InsertColumn(0, _(
'Extension'))
1246 """!Load data into list"""
1247 self.DeleteAllItems()
1248 for ext
in gcmd.RunCommand(
'g.extension.py',
1249 quiet =
True, parent = self, read =
True,
1250 flags =
'a').splitlines():
1252 self.InsertStringItem(sys.maxint, ext)
1255 """!Get extensions to be un-installed
1258 for i
in range(self.GetItemCount()):
1259 if self.IsChecked(i):
1260 name = self.GetItemText(i)
1262 extList.append(name)
1267 """!This panel holds the text from GRASS docs.
1269 GISBASE must be set in the environment to find the html docs dir.
1270 The SYNOPSIS section is skipped, since this Panel is supposed to
1271 be integrated into the cmdPanel and options are obvious there.
1273 def __init__(self, parent, grass_command, text, skip_description,
1275 """!If grass_command is given, the corresponding HTML help
1276 file will be presented, with all links pointing to absolute
1277 paths of local files.
1279 If 'skip_description' is True, the HTML corresponding to
1280 SYNOPSIS will be skipped, thus only presenting the help file
1281 from the DESCRIPTION section onwards.
1283 If 'text' is given, it must be the HTML text to be presented
1287 wx.InitAllImageHandlers()
1288 wx.html.HtmlWindow.__init__(self, parent = parent, **kwargs)
1290 gisbase = os.getenv(
"GISBASE")
1294 self.
fspath = os.path.join(gisbase,
"docs",
"html")
1296 self.SetStandardFonts (size = 10)
1300 if skip_description:
1301 url = os.path.join(self.
fspath, grass_command +
".html")
1303 skip_description = skip_description)
1304 self.history.append(url)
1315 url = linkinfo.GetHref()
1316 if url[:4] !=
'http':
1317 url = os.path.join(self.
fspath, url)
1318 self.history.append(url)
1320 self.parent.OnHistory()
1325 """!Load content from file"""
1326 aLink = re.compile(
r'(<a href="?)(.+\.html?["\s]*>)', re.IGNORECASE)
1327 imgLink = re.compile(
r'(<img src="?)(.+\.[png|gif])', re.IGNORECASE)
1331 for l
in file(htmlFile,
"rb").readlines():
1332 if "DESCRIPTION" in l:
1337 skip = skip_description
1340 findALink = aLink.search(l)
1341 if findALink
is not None:
1342 contents.append(aLink.sub(findALink.group(1)+
1343 self.
fspath+findALink.group(2),l))
1344 findImgLink = imgLink.search(l)
1345 if findImgLink
is not None:
1346 contents.append(imgLink.sub(findImgLink.group(1)+
1347 self.
fspath+findImgLink.group(2),l))
1349 if findALink
is None and findImgLink
is None:
1351 self.SetPage(
"".join(contents))
1357 def __init__(self, parent, grass_command = "index", text = None,
1358 skip_description =
False, **kwargs):
1360 wx.Panel.__init__(self, parent = parent, id = wx.ID_ANY)
1365 self.
btnNext = wx.Button(parent = self, id = wx.ID_ANY,
1367 self.btnNext.Enable(
False)
1368 self.
btnPrev = wx.Button(parent = self, id = wx.ID_ANY,
1369 label = _(
"&Previous"))
1370 self.btnPrev.Enable(
False)
1372 self.btnNext.Bind(wx.EVT_BUTTON, self.
OnNext)
1373 self.btnPrev.Bind(wx.EVT_BUTTON, self.
OnPrev)
1379 sizer = wx.BoxSizer(wx.VERTICAL)
1380 btnSizer = wx.BoxSizer(wx.HORIZONTAL)
1382 btnSizer.Add(item = self.
btnPrev, proportion = 0,
1383 flag = wx.ALL, border = 5)
1384 btnSizer.Add(item = wx.Size(1, 1), proportion = 1)
1385 btnSizer.Add(item = self.
btnNext, proportion = 0,
1386 flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
1388 sizer.Add(item = self.
content, proportion = 1,
1390 sizer.Add(item = btnSizer, proportion = 0,
1393 self.SetSizer(sizer)
1399 path = os.path.join(self.content.fspath, self.
grass_command +
".html")
1400 self.content.history.append(path)
1401 self.content.LoadPage(path)
1404 """!Check if file exists"""
1405 return os.path.isfile(os.path.join(self.content.fspath, self.
grass_command +
".html"))
1408 return self.content.loaded
1411 """!Update buttons"""
1412 nH = len(self.content.history)
1413 iH = self.content.historyIdx
1415 self.btnNext.Enable(
False)
1417 self.btnNext.Enable(
True)
1419 self.btnPrev.Enable(
False)
1421 self.btnPrev.Enable(
True)
1424 """Load next page"""
1425 self.content.historyIdx += 1
1426 idx = self.content.historyIdx
1427 path = self.content.history[idx]
1428 self.content.LoadPage(path)
1434 """Load previous page"""
1435 self.content.historyIdx -= 1
1436 idx = self.content.historyIdx
1437 path = self.content.history[idx]
1438 self.content.LoadPage(path)