[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