[GRASS-SVN] r42163 - in grass/trunk/gui/wxpython: . gui_modules xml
svn_grass at osgeo.org
svn_grass at osgeo.org
Sat May 8 13:34:52 EDT 2010
Author: martinl
Date: 2010-05-08 13:34:51 -0400 (Sat, 08 May 2010)
New Revision: 42163
Modified:
grass/trunk/gui/wxpython/gui_modules/help.py
grass/trunk/gui/wxpython/wxgui.py
grass/trunk/gui/wxpython/xml/menudata.xml
Log:
wxGUI: experimental prototype of extension manager
Modified: grass/trunk/gui/wxpython/gui_modules/help.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/help.py 2010-05-08 17:14:36 UTC (rev 42162)
+++ grass/trunk/gui/wxpython/gui_modules/help.py 2010-05-08 17:34:51 UTC (rev 42163)
@@ -5,9 +5,13 @@
Classes:
- HelpWindow
- - FindModuleWindow
+ - SearchModuleWindow
+ - ItemTree
- MenuTreeWindow
+ - MenuTree
- AboutWindow
+ - InstallExtensionWindow
+ - ExtensionTree
(C) 2008-2010 by the GRASS Development Team
This program is free software under the GNU General Public License
@@ -59,20 +63,20 @@
class SearchModuleWindow(wx.Panel):
"""!Search module window (used in MenuTreeWindow)"""
- def __init__(self, parent, id = wx.ID_ANY, **kwargs):
+ def __init__(self, parent, id = wx.ID_ANY, showLabel = True, **kwargs):
+ self.showLabel = showLabel
+
wx.Panel.__init__(self, parent = parent, id = id, **kwargs)
- self._searchDict = { _('label') : 'label', # i18n workaround
- _('help') : 'help',
- _('command') : 'command',
- _('keywords') : 'keywords' }
+ self._searchDict = { _('description') : 'description',
+ _('command') : 'command',
+ _('keywords') : 'keywords' }
self.searchBy = wx.Choice(parent = self, id = wx.ID_ANY,
- choices = [_('label'),
- _('help'),
- _('command'),
- _('keywords')])
- self.searchBy.SetSelection(3)
+ choices = [_('description'),
+ _('keywords'),
+ _('command')])
+ self.searchBy.SetSelection(0)
self.search = wx.TextCtrl(parent = self, id = wx.ID_ANY,
value = "", size = (-1, 25),
@@ -84,11 +88,12 @@
"""!Do layout"""
# search
sizer = wx.BoxSizer(wx.HORIZONTAL)
- sizer.Add(item = wx.StaticText(parent = self, id = wx.ID_ANY,
- label = _("Find module by:")),
- proportion = 0,
- flag = wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border = 3)
+ if self.showLabel:
+ sizer.Add(item = wx.StaticText(parent = self, id = wx.ID_ANY,
+ label = _("Find module by:")),
+ proportion = 0,
+ flag = wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
+ border = 3)
sizer.Add(item = self.searchBy, proportion = 0,
flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT | wx.RIGHT,
border = 5)
@@ -192,6 +197,14 @@
eval(handler)(event = None, cmd = data['command'].split())
else:
eval(handler)(None)
+
+ def OnShowItem(self, event):
+ """!Show selected item"""
+ self.tree.OnShowItem(event)
+ if self.tree.GetSelected():
+ self.btnRun.Enable()
+ else:
+ self.btnRun.Enable(False)
def OnItemActivated(self, event):
"""!Item activated (double-click)"""
@@ -218,47 +231,17 @@
return
if data['command']:
- label = data['command'] + ' -- ' + data['help']
+ label = data['command'] + ' -- ' + data['description']
else:
- label = data['help']
+ label = data['description']
self.parent.SetStatusText(label, 0)
- def OnShowItem(self, event):
- """!Highlight first found item in menu tree"""
- if len(self.tree.itemsMarked) > 0:
- if self.tree.GetSelected():
- self.tree.ToggleItemSelection(self.tree.GetSelected())
- idx = self.tree.itemsMarked.index(self.tree.GetSelected()) + 1
- else:
- idx = 0
- try:
- self.tree.ToggleItemSelection(self.tree.itemsMarked[idx])
- self.tree.itemSelected = self.tree.itemsMarked[idx]
- self.tree.EnsureVisible(self.tree.itemsMarked[idx])
- except IndexError:
- self.tree.ToggleItemSelection(self.tree.itemsMarked[0]) # reselect first item
- self.tree.EnsureVisible(self.tree.itemsMarked[0])
- self.tree.itemSelected = self.tree.itemsMarked[0]
- else:
- for item in self.tree.root.GetChildren():
- self.tree.Collapse(item)
- itemSelected = self.tree.GetSelection()
- if itemSelected:
- self.tree.ToggleItemSelection(itemSelected)
- self.tree.itemSelected = None
-
- if self.tree.itemSelected:
- self.btnRun.Enable()
- else:
- self.btnRun.Enable(False)
-
def OnUpdateStatusBar(self, event):
"""!Update statusbar text"""
element = self.search.GetSelection()
- self.tree.itemsMarked = self.SearchItems(element = element,
- value = event.GetString())
- self.tree.itemSelected = None
+ self.tree.SearchItems(element = element,
+ value = event.GetString())
nItems = len(self.tree.itemsMarked)
if event.GetString():
@@ -268,6 +251,16 @@
event.Skip()
+class ItemTree(CT.CustomTreeCtrl):
+ def __init__(self, parent, id = wx.ID_ANY,
+ ctstyle = CT.TR_HIDE_ROOT | CT.TR_FULL_ROW_HIGHLIGHT | CT.TR_HAS_BUTTONS |
+ CT.TR_LINES_AT_ROOT | CT.TR_SINGLE, **kwargs):
+ super(ItemTree, self).__init__(parent, id, ctstyle = ctstyle, **kwargs)
+
+ self.root = self.AddRoot(_("Menu tree"))
+ self.itemsMarked = [] # list of marked items
+ self.itemSelected = None
+
def SearchItems(self, element, value):
"""!Search item
@@ -280,43 +273,67 @@
if not value:
return items
- item = self.tree.GetFirstChild(self.tree.root)[0]
- self.__ProcessItem(item, element, value, items)
+ item = self.GetFirstChild(self.root)[0]
+ self._processItem(item, element, value, items)
+ self.itemsMarked = items
+ self.itemSelected = None
+
return items
- def __ProcessItem(self, item, element, value, listOfItems):
+ def _processItem(self, item, element, value, listOfItems):
"""!Search items (used by SearchItems)
-
+
@param item reference item
@param listOfItems list of found items
"""
while item and item.IsOk():
- subItem = self.tree.GetFirstChild(item)[0]
+ subItem = self.GetFirstChild(item)[0]
if subItem:
- self.__ProcessItem(subItem, element, value, listOfItems)
- data = self.tree.GetPyData(item)
+ self._processItem(subItem, element, value, listOfItems)
+ data = self.GetPyData(item)
if data and data.has_key(element) and \
value.lower() in data[element].lower():
listOfItems.append(item)
- item = self.tree.GetNextSibling(item)
-
-class MenuTree(CT.CustomTreeCtrl):
+ item = self.GetNextSibling(item)
+
+ def GetSelected(self):
+ """!Get selected item"""
+ return self.itemSelected
+
+ def OnShowItem(self, event):
+ """!Highlight first found item in menu tree"""
+ if len(self.itemsMarked) > 0:
+ if self.GetSelected():
+ self.ToggleItemSelection(self.GetSelected())
+ idx = self.itemsMarked.index(self.GetSelected()) + 1
+ else:
+ idx = 0
+ try:
+ self.ToggleItemSelection(self.itemsMarked[idx])
+ self.itemSelected = self.itemsMarked[idx]
+ self.EnsureVisible(self.itemsMarked[idx])
+ except IndexError:
+ self.ToggleItemSelection(self.itemsMarked[0]) # reselect first item
+ self.EnsureVisible(self.itemsMarked[0])
+ self.itemSelected = self.itemsMarked[0]
+ else:
+ for item in self.root.GetChildren():
+ self.Collapse(item)
+ itemSelected = self.GetSelection()
+ if itemSelected:
+ self.ToggleItemSelection(itemSelected)
+ self.itemSelected = None
+
+class MenuTree(ItemTree):
"""!Menu tree class"""
- def __init__(self, parent, data, id = wx.ID_ANY,
- ctstyle = CT.TR_HIDE_ROOT | CT.TR_FULL_ROW_HIGHLIGHT | CT.TR_HAS_BUTTONS | \
- CT.TR_LINES_AT_ROOT | CT.TR_SINGLE,
- **kwargs):
+ def __init__(self, parent, data, **kwargs):
self.parent = parent
self.menudata = data
- super(MenuTree, self).__init__(parent, id, ctstyle = ctstyle, **kwargs)
-
- self.root = self.AddRoot(_("Menu tree"))
- self.itemsMarked = [] # list of marked items
- self.itemSelected = None
+ super(MenuTree, self).__init__(parent, **kwargs)
def Load(self, data = None):
"""!Load menu data tree
@@ -349,18 +366,14 @@
itemNew = self.AppendItem(parentId = item,
text = eachItem[0])
- data = { 'label' : eachItem[0],
- 'help' : eachItem[1],
+ data = { 'item' : eachItem[0],
+ 'description' : eachItem[1],
'handler' : eachItem[2],
'command' : eachItem[3],
'keywords' : eachItem[4] }
self.SetPyData(itemNew, data)
- def GetSelected(self):
- """!Get selected item"""
- return self.itemSelected
-
class AboutWindow(wx.Frame):
def __init__(self, parent):
"""!Create custom About Window
@@ -647,3 +660,224 @@
def OnCloseWindow(self, event):
"""!Close window"""
self.Close()
+
+class InstallExtensionWindow(wx.Frame):
+ def __init__(self, parent, id = wx.ID_ANY,
+ title = _("Fetch & install new extension from GRASS Addons"), **kwargs):
+ self.parent = parent
+
+ wx.Frame.__init__(self, parent = parent, id = id, title = title, **kwargs)
+
+ self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
+
+ self.findBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
+ label=" %s " % _("Find extension by"))
+ self.treeBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
+ label=" %s " % _("List of extensions"))
+
+ self.search = SearchModuleWindow(parent = self.panel, showLabel = False)
+
+ self.tree = ExtensionTree(parent = self.panel, log = parent.GetLogWindow())
+
+ self.statusbar = self.CreateStatusBar(0)
+
+ self.btnFetch = wx.Button(parent = self.panel, id = wx.ID_ANY,
+ label = _("&Fetch"))
+ self.btnFetch.SetToolTipString(_("Fetch list of available modules from GRASS Addons SVN repository"))
+ self.btnClose = wx.Button(parent = self.panel, id = wx.ID_CLOSE)
+ self.btnInstall = wx.Button(parent = self.panel, id = wx.ID_ANY,
+ label = _("&Install"))
+ self.btnInstall.SetToolTipString(_("Install selected add-ons GRASS module"))
+ self.btnInstall.Enable(False)
+
+ self.btnClose.Bind(wx.EVT_BUTTON, self.OnCloseWindow)
+ self.btnFetch.Bind(wx.EVT_BUTTON, self.OnFetch)
+ self.btnInstall.Bind(wx.EVT_BUTTON, self.OnInstall)
+ self.tree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnItemActivated)
+ self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnItemSelected)
+ self.search.Bind(wx.EVT_TEXT_ENTER, self.OnShowItem)
+ self.search.Bind(wx.EVT_TEXT, self.OnUpdateStatusBar)
+
+ self._layout()
+
+ def _layout(self):
+ """!Do layout"""
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ findSizer = wx.StaticBoxSizer(self.findBox, wx.HORIZONTAL)
+ findSizer.Add(item = self.search, proportion = 1,
+ flag = wx.ALL, border = 1)
+ findSizer.Add(item = self.btnFetch, proportion = 0,
+ flag = wx.ALL | wx.ALIGN_CENTER_VERTICAL, border = 1)
+
+ treeSizer = wx.StaticBoxSizer(self.treeBox, wx.HORIZONTAL)
+ treeSizer.Add(item = self.tree, proportion = 1,
+ flag = wx.ALL | wx.EXPAND, border = 1)
+
+ btnSizer = wx.BoxSizer(wx.HORIZONTAL)
+ btnSizer.Add(item = self.btnClose, proportion = 0,
+ flag = wx.LEFT | wx.RIGHT, border = 5)
+ btnSizer.Add(item = self.btnInstall, proportion = 0,
+ flag = wx.LEFT | wx.RIGHT, border = 5)
+
+ sizer.Add(item = findSizer, proportion = 0,
+ flag = wx.ALL | wx.EXPAND, border = 3)
+ sizer.Add(item = treeSizer, proportion = 1,
+ flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
+ sizer.Add(item = btnSizer, proportion=0,
+ flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
+
+ self.panel.SetSizer(sizer)
+ sizer.Fit(self.panel)
+
+ self.Layout()
+
+ def _install(self, name):
+ if not name:
+ return
+ log = self.parent.GetLogWindow()
+ log.RunCmd(['g.extension', 'extension=' + name])
+ self.OnCloseWindow(None)
+
+ def OnUpdateStatusBar(self, event):
+ """!Update statusbar text"""
+ element = self.search.GetSelection()
+ self.tree.SearchItems(element = element,
+ value = event.GetString())
+
+ nItems = len(self.tree.itemsMarked)
+ if event.GetString():
+ self.SetStatusText(_("%d items match") % nItems, 0)
+ else:
+ self.SetStatusText("", 0)
+
+ event.Skip()
+
+ def OnCloseWindow(self, event):
+ """!Close window"""
+ self.Destroy()
+
+ def OnFetch(self, event):
+ """!Fetch list of available extensions"""
+ self.SetStatusText(_("Fetching list of modules from GRASS-Addons SVN (be patient)..."), 0)
+ self.tree.Load()
+ self.SetStatusText("", 0)
+
+ def OnItemActivated(self, event):
+ item = event.GetItem()
+ data = self.tree.GetPyData(item)
+ if data and data.has_key('command'):
+ self._install(data['command'])
+
+ def OnInstall(self, event):
+ """!Install selected extension"""
+ item = self.tree.GetSelected()
+ if not item.IsOk():
+ return
+ self._install(self.tree.GetItemText(item))
+
+ def OnItemSelected(self, event):
+ """!Item selected"""
+ item = event.GetItem()
+ self.tree.itemSelected = item
+ data = self.tree.GetPyData(item)
+ if not data:
+ self.SetStatusText('', 0)
+ self.btnInstall.Enable(False)
+ else:
+ self.SetStatusText(data.get('description', ''), 0)
+ self.btnInstall.Enable(True)
+
+ def OnShowItem(self, event):
+ """!Show selected item"""
+ self.tree.OnShowItem(event)
+ if self.tree.GetSelected():
+ self.btnInstall.Enable()
+ else:
+ self.btnInstall.Enable(False)
+
+class ExtensionTree(ItemTree):
+ """!List of available extensions"""
+ def __init__(self, parent, log, id = wx.ID_ANY,
+ ctstyle = CT.TR_HIDE_ROOT | CT.TR_FULL_ROW_HIGHLIGHT | CT.TR_HAS_BUTTONS |
+ CT.TR_LINES_AT_ROOT | CT.TR_SINGLE,
+ **kwargs):
+ self.parent = parent # GMFrame
+ self.log = log
+
+ super(ExtensionTree, self).__init__(parent, id, ctstyle = ctstyle, **kwargs)
+
+ self._initTree()
+
+ def _initTree(self):
+ for prefix in ('display', 'database',
+ 'general', 'imagery',
+ 'misc', 'postscript', 'paint',
+ 'raster', 'raster3D', 'sites', 'vector'):
+ self.AppendItem(parentId = self.root,
+ text = prefix)
+
+ def _expandPrefix(self, c):
+ name = { 'd' : 'display',
+ 'db' : 'database',
+ 'g' : 'general',
+ 'i' : 'imagery',
+ 'm' : 'misc',
+ 'ps' : 'postscript',
+ 'p' : 'paint',
+ 'r' : 'raster',
+ 'r3' : 'raster3D',
+ 's' : 'sites',
+ 'v' : 'vector' }
+
+ if name.has_key(c):
+ return name[c]
+
+ return c
+
+ def _findItem(self, text):
+ """!Find item"""
+ item = self.GetFirstChild(self.root)[0]
+ while item and item.IsOk():
+ if text == self.GetItemText(item):
+ return item
+
+ item = self.GetNextSibling(item)
+
+ return None
+
+ def Load(self):
+ """!Load list of extensions"""
+ self.DeleteAllItems()
+ self.root = self.AddRoot(_("Menu tree"))
+ self._initTree()
+
+ ret = gcmd.RunCommand('g.extension', read = True,
+ flags = 'g', quiet = True)
+ if not ret:
+ return
+
+ mdict = dict()
+ for line in ret.splitlines():
+ key, value = line.split('=', 1)
+ if key == 'name':
+ prefix, name = value.split('.', 1)
+ if not mdict.has_key(prefix):
+ mdict[prefix] = dict()
+ mdict[prefix][name] = dict()
+ else:
+ mdict[prefix][name][key] = value
+
+ for prefix in mdict.keys():
+ prefixName = self._expandPrefix(prefix)
+ item = self._findItem(prefixName)
+ names = mdict[prefix].keys()
+ names.sort()
+ for name in names:
+ new = self.AppendItem(parentId = item,
+ text = prefix + '.' + name)
+ data = dict()
+ for key in mdict[prefix][name].keys():
+ data[key] = mdict[prefix][name][key]
+
+ self.SetPyData(new, data)
+
Modified: grass/trunk/gui/wxpython/wxgui.py
===================================================================
--- grass/trunk/gui/wxpython/wxgui.py 2010-05-08 17:14:36 UTC (rev 42162)
+++ grass/trunk/gui/wxpython/wxgui.py 2010-05-08 17:34:51 UTC (rev 42163)
@@ -93,6 +93,7 @@
from gui_modules.debug import Debug
from gui_modules.help import MenuTreeWindow
from gui_modules.help import AboutWindow
+from gui_modules.help import InstallExtensionWindow
from icons.icon import Icons
UserSettings = preferences.globalSettings
@@ -916,6 +917,12 @@
self.goutput.RunCmd(cmdlist)
+ def OnInstallExtension(self, event):
+ """!Install extension from GRASS Addons SVN repository"""
+ win = InstallExtensionWindow(self, size = (500, 300))
+ win.CentreOnScreen()
+ win.Show()
+
def OnPreferences(self, event):
"""!General GUI preferences/settings"""
if not self.dialogs['preferences']:
Modified: grass/trunk/gui/wxpython/xml/menudata.xml
===================================================================
--- grass/trunk/gui/wxpython/xml/menudata.xml 2010-05-08 17:14:36 UTC (rev 42162)
+++ grass/trunk/gui/wxpython/xml/menudata.xml 2010-05-08 17:34:51 UTC (rev 42163)
@@ -782,6 +782,11 @@
</menu>
<separator />
<menuitem>
+ <label>Install new extension from add-ons</label>
+ <help>Install new extension from GRASS AddOns SVN repository.</help>
+ <handler>OnInstallExtension</handler>
+ </menuitem>
+ <menuitem>
<label>Manage add-ons extensions</label>
<help>Tool to maintain the extensions in local GRASS installation.</help>
<keywords>general,installation,extensions</keywords>
More information about the grass-commit
mailing list