[GRASS-SVN] r42204 - grass/trunk/gui/wxpython/gui_modules

svn_grass at osgeo.org svn_grass at osgeo.org
Mon May 10 05:01:04 EDT 2010


Author: martinl
Date: 2010-05-10 05:01:04 -0400 (Mon, 10 May 2010)
New Revision: 42204

Added:
   grass/trunk/gui/wxpython/gui_modules/ghelp.py
Removed:
   grass/trunk/gui/wxpython/gui_modules/help.py
Modified:
   grass/trunk/gui/wxpython/gui_modules/__init__.py
   grass/trunk/gui/wxpython/gui_modules/gmodeler.py
   grass/trunk/gui/wxpython/gui_modules/goutput.py
Log:
wxGUI: improve SearchModuleWindow


Modified: grass/trunk/gui/wxpython/gui_modules/__init__.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/__init__.py	2010-05-09 21:06:48 UTC (rev 42203)
+++ grass/trunk/gui/wxpython/gui_modules/__init__.py	2010-05-10 09:01:04 UTC (rev 42204)
@@ -8,6 +8,7 @@
     "gcmd.py",
     "gdialogs.py",
     "georect.py",
+    "ghelp.py"
     "globalvar.py",
     "goutput.py",
     "gselect.py",

Copied: grass/trunk/gui/wxpython/gui_modules/ghelp.py (from rev 42181, grass/trunk/gui/wxpython/gui_modules/help.py)
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/ghelp.py	                        (rev 0)
+++ grass/trunk/gui/wxpython/gui_modules/ghelp.py	2010-05-10 09:01:04 UTC (rev 42204)
@@ -0,0 +1,994 @@
+"""!
+ at package help.py
+
+ at brief Help window
+
+Classes:
+ - HelpWindow
+ - 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
+(>=v2). Read the file COPYING that comes with GRASS for details.
+
+ at author Martin Landa <landa.martin gmail.com>
+"""
+
+import os
+
+import wx
+try:
+    import wx.lib.agw.customtreectrl as CT
+#    import wx.lib.agw.hyperlink as hl
+except ImportError:
+    import wx.lib.customtreectrl as CT
+#    import wx.lib.hyperlink as hl
+import wx.lib.flatnotebook as FN
+import  wx.lib.scrolledpanel as scrolled
+
+import menudata
+import gcmd
+import globalvar
+import menuform
+
+class HelpWindow(wx.Frame):
+    """!GRASS Quickstart help window"""
+    def __init__(self, parent, id, title, size, file):
+
+        wx.Frame.__init__(self, parent=parent, id=id, title=title, size=size)
+
+        sizer = wx.BoxSizer(wx.VERTICAL)
+
+        # text
+        helpFrame = wx.html.HtmlWindow(parent=self, id=wx.ID_ANY)
+        helpFrame.SetStandardFonts (size = 10)
+        helpFrame.SetBorders(10)
+        wx.InitAllImageHandlers()
+
+        helpFrame.LoadFile(file)
+        self.Ok = True
+
+        sizer.Add(item=helpFrame, proportion=1, flag=wx.EXPAND)
+
+        self.SetAutoLayout(True)
+        self.SetSizer(sizer)
+        #        sizer.Fit(self)
+        #        sizer.SetSizeHints(self)
+        self.Layout()
+
+class SearchModuleWindow(wx.Panel):
+    """!Search module window (used in MenuTreeWindow)"""
+    def __init__(self, parent, id = wx.ID_ANY, cmdPrompt = None, showChoice = True, **kwargs):
+        self.showChoice = showChoice
+        self.cmdPrompt  = cmdPrompt
+        
+        wx.Panel.__init__(self, parent = parent, id = id, **kwargs)
+        
+        self._searchDict = { _('description') : 'description',
+                             _('command')     : 'command',
+                             _('keywords')    : 'keywords' }
+
+        self.box = wx.StaticBox(parent = self, id = wx.ID_ANY,
+                                label=" %s " % _("Find module(s)"))
+        
+        self.searchBy = wx.Choice(parent = self, id = wx.ID_ANY,
+                                  choices = [_('description'),
+                                             _('keywords'),
+                                             _('command')])
+        self.searchBy.SetSelection(0)
+        
+        self.search = wx.TextCtrl(parent = self, id = wx.ID_ANY,
+                                  value = "", size = (-1, 25),
+                                  style = wx.TE_PROCESS_ENTER)
+        self.search.Bind(wx.EVT_TEXT, self.OnSearchModule)
+        
+        if self.showChoice:
+            self.searchTip  = menuform.StaticWrapText(parent = self, id = wx.ID_ANY,
+                                                      size = (-1, 35))
+            
+            self.searchChoice = wx.Choice(parent = self, id = wx.ID_ANY)
+            self.searchChoice.Bind(wx.EVT_CHOICE, self.OnSelectModule)
+        
+        self._layout()
+
+    def _layout(self):
+        """!Do layout"""
+        sizer = wx.StaticBoxSizer(self.box, wx.HORIZONTAL)
+        gridSizer = wx.GridBagSizer(hgap = 3, vgap = 3)
+        gridSizer.AddGrowableCol(1)
+        
+        gridSizer.Add(item = self.searchBy,
+                      flag=wx.ALIGN_CENTER_VERTICAL, pos = (0, 0))
+        gridSizer.Add(item = self.search,
+                      flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, pos = (0, 1))
+        if self.showChoice:
+            gridSizer.Add(item = self.searchTip,
+                          flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, pos = (1, 0), span = (1, 2))
+            gridSizer.Add(item = self.searchChoice,
+                          flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, pos = (2, 0), span = (1, 2))
+        
+        sizer.Add(item = gridSizer, proportion = 1)
+        
+        self.SetSizer(sizer)
+        sizer.Fit(self)
+
+    def GetSelection(self):
+        """!Get selected element"""
+        selection = self.searchBy.GetStringSelection()
+        
+        return self._searchDict[selection]
+
+    def SetSelection(self, i):
+        """!Set selection element"""
+        self.searchBy.SetSelection(i)
+
+    def OnSearchModule(self, event):
+        """!Search module by keywords or description"""
+        if not self.cmdPrompt:
+            event.Skip()
+            return
+        
+        text = event.GetString()
+        if not text:
+            self.cmdPrompt.SetFilter(None)
+            return
+        
+        modules = dict()
+        iFound = 0
+        for module, data in self.cmdPrompt.moduleDesc.iteritems():
+            found = False
+            if self.searchBy.GetSelection() == 0: # -> description
+                if text in data['desc']:
+                    found = True
+            else: # -> keywords
+                if self.cmdPrompt.CheckKey(text, data['keywords']):
+                    found = True
+            
+            if found:
+                iFound += 1
+                try:
+                    group, name = module.split('.')
+                except ValueError:
+                    continue # TODO
+                
+                if not modules.has_key(group):
+                    modules[group] = list()
+                modules[group].append(name)
+        
+        self.cmdPrompt.SetFilter(modules)
+        self.searchTip.SetLabel(_("%d modules found") % iFound)
+        self.searchChoice.SetItems(self.cmdPrompt.GetCommandItems())
+        
+    def OnSelectModule(self, event):
+        """!Module selected from choice, update command prompt"""
+        cmd  = event.GetString().split(' ', 1)[0]
+        text = cmd + ' '
+        pos = len(text)
+
+        if self.cmdPrompt:
+            self.cmdPrompt.SetText(text)
+            self.cmdPrompt.SetSelectionStart(pos)
+            self.cmdPrompt.SetCurrentPos(pos)
+            self.cmdPrompt.SetFocus()
+        
+        desc = self.cmdPrompt.GetCommandDesc(cmd)
+        self.searchTip.SetLabel(desc)
+        
+class MenuTreeWindow(wx.Panel):
+    """!Show menu tree"""
+    def __init__(self, parent, id = wx.ID_ANY, **kwargs):
+        self.parent = parent # LayerManager
+        
+        wx.Panel.__init__(self, parent = parent, id = id, **kwargs)
+        
+        self.dataBox = wx.StaticBox(parent = self, id = wx.ID_ANY,
+                                    label=" %s " % _("Menu tree (double-click to run command)"))
+        # tree
+        self.tree = MenuTree(parent = self, data = menudata.ManagerData())
+        self.tree.Load()
+
+        # search widget
+        self.search = SearchModuleWindow(parent = self, showChoice = False)
+        
+        # buttons
+        self.btnRun   = wx.Button(self, id = wx.ID_OK, label = _("Run"))
+        self.btnRun.SetToolTipString(_("Run selected command"))
+        self.btnRun.Enable(False)
+        
+        # bindings
+        self.btnRun.Bind(wx.EVT_BUTTON,            self.OnRun)
+        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()
+        
+        self.search.SetFocus()
+        
+    def _layout(self):
+        """!Do dialog layout"""
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        
+        # body
+        dataSizer = wx.StaticBoxSizer(self.dataBox, wx.HORIZONTAL)
+        dataSizer.Add(item = self.tree, proportion =1,
+                      flag = wx.EXPAND)
+        
+        # buttons
+        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
+        btnSizer.Add(item = self.btnRun, proportion = 0,
+                     flag = wx.LEFT | wx.RIGHT, border = 5)
+        
+        sizer.Add(item = dataSizer, proportion = 1,
+                  flag = wx.EXPAND | wx.ALL, border = 5)
+
+        sizer.Add(item = self.search, proportion=0,
+                  flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
+        
+        sizer.Add(item = btnSizer, proportion=0,
+                  flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
+        
+        sizer.Fit(self)
+        sizer.SetSizeHints(self)
+        
+        self.SetSizer(sizer)
+        
+        self.Fit()
+        self.SetAutoLayout(True)        
+        self.Layout()
+        
+    def OnCloseWindow(self, event):
+        """!Close window"""
+        self.Destroy()
+        
+    def OnRun(self, event):
+        """!Run selected command"""
+        if not self.tree.GetSelected():
+            return # should not happen
+        
+        data = self.tree.GetPyData(self.tree.GetSelected())
+        if not data:
+            return
+
+        handler = 'self.parent.' + data['handler'].lstrip('self.')
+        if data['handler'] == 'self.OnXTerm':
+            wx.MessageBox(parent = self,
+                          message = _('You must run this command from the menu or command line',
+                                      'This command require an XTerm'),
+                          caption = _('Message'), style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
+        elif data['command']:
+            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)"""
+        item = event.GetItem()
+        if not item or not item.IsOk():
+            return
+        
+        data = self.tree.GetPyData(item)
+        if not data or not data.has_key('command'):
+            return
+        
+        self.tree.itemSelected = item
+        
+        self.OnRun(None)
+        
+    def OnItemSelected(self, event):
+        """!Item selected"""
+        item = event.GetItem()
+        if not item or not item.IsOk():
+            return
+        
+        data = self.tree.GetPyData(item)
+        if not data or not data.has_key('command'):
+            return
+        
+        if data['command']:
+            label = data['command'] + ' -- ' + data['description']
+        else:
+            label = data['description']
+        
+        self.parent.SetStatusText(label, 0)
+        
+    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.parent.SetStatusText(_("%d items match") % nItems, 0)
+        else:
+            self.parent.SetStatusText("", 0)
+        
+        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 
+
+        @param element element index (see self.searchBy)
+        @param value
+
+        @return list of found tree items
+        """
+        items = list()
+        if not value:
+            return 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):
+        """!Search items (used by SearchItems)
+        
+        @param item reference item
+        @param listOfItems list of found items
+        """
+        while item and item.IsOk():
+            subItem = self.GetFirstChild(item)[0]
+            if subItem:
+                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.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, **kwargs):
+        self.parent   = parent
+        self.menudata = data
+
+        super(MenuTree, self).__init__(parent, **kwargs)
+        
+    def Load(self, data = None):
+        """!Load menu data tree
+
+        @param data menu data (None to use self.menudata)
+        """
+        if not data:
+            data = self.menudata
+        
+        self.itemsMarked = [] # list of marked items
+        for eachMenuData in data.GetMenu():
+            for label, items in eachMenuData:
+                item = self.AppendItem(parentId = self.root,
+                                       text = label.replace('&', ''))
+                self.__AppendItems(item, items)
+        
+    def __AppendItems(self, item, data):
+        """!Append items into tree (used by Load()
+        
+        @param item tree item (parent)
+        @parent data menu data"""
+        for eachItem in data:
+            if len(eachItem) == 2:
+                if eachItem[0]:
+                    itemSub = self.AppendItem(parentId = item,
+                                    text = eachItem[0])
+                self.__AppendItems(itemSub, eachItem[1])
+            else:
+                if eachItem[0]:
+                    itemNew = self.AppendItem(parentId = item,
+                                              text = eachItem[0])
+                    
+                    data = { 'item'        : eachItem[0],
+                             'description' : eachItem[1],
+                             'handler'  : eachItem[2],
+                             'command'  : eachItem[3],
+                             'keywords' : eachItem[4] }
+                    
+                    self.SetPyData(itemNew, data)
+        
+class AboutWindow(wx.Frame):
+    def __init__(self, parent):
+        """!Create custom About Window
+
+        @todo improve styling
+        """
+        wx.Frame.__init__(self, parent=parent, id=wx.ID_ANY, size=(550,400), 
+                          title=_('About GRASS GIS'))
+        
+        panel = wx.Panel(parent = self, id = wx.ID_ANY)
+        
+        # icon
+        self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
+
+        # get version and web site
+        version, svn_gis_h_rev, svn_gis_h_date = gcmd.RunCommand('g.version',
+                                                                 flags = 'r',
+                                                                 read = True).splitlines()
+        
+        infoTxt = wx.Panel(parent = panel, id = wx.ID_ANY)
+        infoSizer = wx.BoxSizer(wx.VERTICAL)
+        infoGridSizer = wx.GridBagSizer(vgap=5, hgap=5)
+        infoGridSizer.AddGrowableCol(0)
+        infoGridSizer.AddGrowableCol(1)
+        logo = os.path.join(globalvar.ETCDIR, "gui", "icons", "grass.ico")
+        logoBitmap = wx.StaticBitmap(parent = infoTxt, id = wx.ID_ANY,
+                                     bitmap = wx.Bitmap(name = logo,
+                                                        type = wx.BITMAP_TYPE_ICO))
+        infoSizer.Add(item = logoBitmap, proportion = 0,
+                      flag = wx.ALL | wx.ALIGN_CENTER, border = 25)
+        
+        info = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
+                             label = version.replace('GRASS', 'GRASS GIS').strip() + '\n\n')
+        info.SetFont(wx.Font(13, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
+        infoSizer.Add(item = info, proportion = 0,
+                          flag = wx.BOTTOM | wx.ALIGN_CENTER, border = 15)
+
+        infoGridSizer.Add(item = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
+                                               label = _('Official GRASS site:')),
+                          pos = (0, 0),
+                          flag = wx.ALIGN_RIGHT)
+
+        infoGridSizer.Add(item = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
+                                               label = 'http://grass.osgeo.org'),
+                          pos = (0, 1),
+                          flag = wx.ALIGN_LEFT)
+
+        # infoGridSizer.Add(item = hl.HyperLinkCtrl(parent = self, id = wx.ID_ANY,
+        #                                           label = 'http://grass.osgeo.org',
+        #                                           URL = 'http://grass.osgeo.org'),
+        #                   pos = (0, 1),
+        #                   flag = wx.LEFT)
+        
+        infoGridSizer.Add(item = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
+                                               label = _('GIS Library Revision:')),
+                          pos = (2, 0),
+                          flag = wx.ALIGN_RIGHT)
+        
+        infoGridSizer.Add(item = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
+                                               label = svn_gis_h_rev.split(' ')[1] + ' (' +
+                                               svn_gis_h_date.split(' ')[1] + ')'),
+                          pos = (2, 1),
+                          flag = wx.ALIGN_LEFT)
+
+        infoSizer.Add(item = infoGridSizer,
+                      proportion = 1,
+                      flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL,
+                      border = 25)
+        
+        #
+        # create pages
+        #
+        copyrightwin = self.PageCopyright()
+        licensewin   = self.PageLicense()
+        authorwin    = self.PageCredit()
+        contribwin   = self.PageContributors()
+        transwin     = self.PageTranslators()
+
+        # create a flat notebook for displaying information about GRASS
+        nbstyle = FN.FNB_VC8 | \
+                FN.FNB_BACKGROUND_GRADIENT | \
+                FN.FNB_TABS_BORDER_SIMPLE | \
+                FN.FNB_NO_X_BUTTON
+        
+        aboutNotebook = FN.FlatNotebook(panel, id=wx.ID_ANY, style=nbstyle)
+        aboutNotebook.SetTabAreaColour(globalvar.FNPageColor)
+        
+        # make pages for About GRASS notebook
+        pg1 = aboutNotebook.AddPage(infoTxt,      text=_("Info"))
+        pg2 = aboutNotebook.AddPage(copyrightwin, text=_("Copyright"))
+        pg3 = aboutNotebook.AddPage(licensewin,   text=_("License"))
+        pg4 = aboutNotebook.AddPage(authorwin,    text=_("Authors"))
+        pg5 = aboutNotebook.AddPage(contribwin,   text=_("Contributors"))
+        pg5 = aboutNotebook.AddPage(transwin,     text=_("Translators"))
+        
+        wx.CallAfter(aboutNotebook.SetSelection, 0)
+        
+        # buttons
+        btnClose = wx.Button(parent = panel, id = wx.ID_CLOSE)
+        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
+        btnSizer.Add(item = btnClose, proportion = 0,
+                     flag = wx.ALL | wx.ALIGN_RIGHT,
+                     border = 5)
+        # bindings
+        # self.aboutNotebook.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.OnAGPageChanged)
+        btnClose.Bind(wx.EVT_BUTTON, self.OnCloseWindow)
+
+        infoTxt.SetSizer(infoSizer)
+        infoSizer.Fit(infoTxt)
+        
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        sizer.Add(item=aboutNotebook, proportion=1,
+                  flag=wx.EXPAND | wx.ALL, border=1)
+        sizer.Add(item=btnSizer, proportion=0,
+                  flag=wx.ALL | wx.ALIGN_RIGHT, border=1)
+        panel.SetSizer(sizer)
+        self.Layout()
+    
+    def PageCopyright(self):
+        """Copyright information"""
+        copyfile = os.path.join(os.getenv("GISBASE"), "COPYING")
+        if os.path.exists(copyfile):
+            copyrightFile = open(copyfile, 'r')
+            copytext = copyrightFile.read()
+            copyrightFile.close()
+        else:
+            copytext = _('%s file missing') % 'COPYING'
+        
+        # put text into a scrolling panel
+        copyrightwin = scrolled.ScrolledPanel(self, id=wx.ID_ANY, 
+                                              size=wx.DefaultSize,
+                                              style = wx.TAB_TRAVERSAL | wx.SUNKEN_BORDER)
+        copyrighttxt = wx.StaticText(copyrightwin, id=wx.ID_ANY, label=copytext)
+        copyrightwin.SetAutoLayout(True)
+        copyrightwin.sizer = wx.BoxSizer(wx.VERTICAL)
+        copyrightwin.sizer.Add(item=copyrighttxt, proportion=1,
+                               flag=wx.EXPAND | wx.ALL, border=3)
+        copyrightwin.SetSizer(copyrightwin.sizer)
+        copyrightwin.Layout()
+        copyrightwin.SetupScrolling()
+        
+        return copyrightwin
+    
+    def PageLicense(self):
+        """Licence about"""
+        licfile = os.path.join(os.getenv("GISBASE"), "GPL.TXT")
+        if os.path.exists(licfile):
+            licenceFile = open(licfile, 'r')
+            license = ''.join(licenceFile.readlines())
+            licenceFile.close()
+        else:
+            license = _('%s file missing') % 'GPL.TXT'
+        # put text into a scrolling panel
+        licensewin = scrolled.ScrolledPanel(self, id=wx.ID_ANY, 
+                                            style = wx.TAB_TRAVERSAL | wx.SUNKEN_BORDER)
+        licensetxt = wx.StaticText(licensewin, id=wx.ID_ANY, label=license)
+        licensewin.SetAutoLayout(True)
+        licensewin.sizer = wx.BoxSizer(wx.VERTICAL)
+        licensewin.sizer.Add(item=licensetxt, proportion=1,
+                flag=wx.EXPAND | wx.ALL, border=3)
+        licensewin.SetSizer(licensewin.sizer)
+        licensewin.Layout()
+        licensewin.SetupScrolling()
+        
+        return licensewin
+    
+    def PageCredit(self):
+        """Credit about"""
+                # credits
+        authfile = os.path.join(os.getenv("GISBASE"), "AUTHORS")
+        if os.path.exists(authfile):
+            authorsFile = open(authfile, 'r')
+            authors = unicode(''.join(authorsFile.readlines()), "utf-8")
+            authorsFile.close()
+        else:
+            authors = _('%s file missing') % 'AUTHORS'
+        authorwin = scrolled.ScrolledPanel(self, id=wx.ID_ANY, 
+                                           style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
+        authortxt = wx.StaticText(authorwin, id=wx.ID_ANY, label=authors)
+        authorwin.SetAutoLayout(1)
+        authorwin.SetupScrolling()
+        authorwin.sizer = wx.BoxSizer(wx.VERTICAL)
+        authorwin.sizer.Add(item=authortxt, proportion=1,
+                flag=wx.EXPAND | wx.ALL, border=3)
+        authorwin.SetSizer(authorwin.sizer)
+        authorwin.Layout()      
+        
+        return authorwin
+
+    def PageContributors(self):
+        """Contributors info"""
+        contribfile = os.path.join(os.getenv("GISBASE"), "contributors.csv")
+        if os.path.exists(contribfile):
+            contribFile = open(contribfile, 'r')
+            contribs = list()
+            for line in contribFile.readlines():
+                cvs_id, name, email, country, osgeo_id, rfc2_agreed = line.split(',')
+                contribs.append((name, email, country, osgeo_id))
+            contribs[0] = (_('Name'), _('E-mail'), _('Country'), _('OSGeo_ID'))
+            contribFile.close()
+        else:
+            contribs = None
+        
+        contribwin = scrolled.ScrolledPanel(self, id=wx.ID_ANY, 
+                                           style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
+        contribwin.SetAutoLayout(1)
+        contribwin.SetupScrolling()
+        contribwin.sizer = wx.BoxSizer(wx.VERTICAL)
+        
+        if not contribs:
+            contribtxt = wx.StaticText(contribwin, id=wx.ID_ANY,
+                                       label=_('%s file missing') % 'contibutors.csv')
+            contribwin.sizer.Add(item=contribtxt, proportion=1,
+                                 flag=wx.EXPAND | wx.ALL, border=3)
+        else:
+            contribBox = wx.FlexGridSizer(cols=4, vgap=5, hgap=5)
+            for developer in contribs:
+                for item in developer:
+                    contribBox.Add(item = wx.StaticText(parent = contribwin, id = wx.ID_ANY,
+                                                        label = item))
+            contribwin.sizer.Add(item=contribBox, proportion=1,
+                                 flag=wx.EXPAND | wx.ALL, border=3)
+        
+        contribwin.SetSizer(contribwin.sizer)
+        contribwin.Layout()      
+        
+        return contribwin
+
+    def PageTranslators(self):
+        """Translators info"""
+        translatorsfile = os.path.join(os.getenv("GISBASE"), "translators.csv")
+        if os.path.exists(translatorsfile):
+            translatorsFile = open(translatorsfile, 'r')
+            translators = dict()
+            for line in translatorsFile.readlines()[1:]:
+                name, email, languages = line.rstrip('\n').split(',')
+                for language in languages.split(' '):
+                    if not translators.has_key(language):
+                        translators[language] = list()
+                    translators[language].append((name, email))
+            translatorsFile.close()
+        else:
+            translators = None
+        
+        translatorswin = scrolled.ScrolledPanel(self, id=wx.ID_ANY, 
+                                           style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
+        translatorswin.SetAutoLayout(1)
+        translatorswin.SetupScrolling()
+        translatorswin.sizer = wx.BoxSizer(wx.VERTICAL)
+        
+        if not translators:
+            translatorstxt = wx.StaticText(translatorswin, id=wx.ID_ANY,
+                                           label=_('%s file missing') % 'translators.csv')
+            translatorswin.sizer.Add(item=translatorstxt, proportion=1,
+                                 flag=wx.EXPAND | wx.ALL, border=3)
+        else:
+            translatorsBox = wx.FlexGridSizer(cols=3, vgap=5, hgap=5)
+            languages = translators.keys()
+            languages.sort()
+            translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
+                                                    label = _('Name')))
+            translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
+                                                    label = _('E-mail')))
+            translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
+                                                    label = _('Language')))
+            for lang in languages:
+                for translator in translators[lang]:
+                    name, email = translator
+                    translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
+                                                            label =  unicode(name, "utf-8")))
+                    translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
+                                                            label = email))
+                    translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
+                                                            label = lang))
+            
+            translatorswin.sizer.Add(item=translatorsBox, proportion=1,
+                                 flag=wx.EXPAND | wx.ALL, border=3)
+        
+        translatorswin.SetSizer(translatorswin.sizer)
+        translatorswin.Layout()      
+        
+        return translatorswin
+    
+    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.repoBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
+                                    label=" %s " % _("Repository"))
+        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.repo = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY,
+                                value = 'https://svn.osgeo.org/grass/grass-addons')
+        self.fullDesc = wx.CheckBox(parent = self.panel, id=wx.ID_ANY,
+                                    label = _("Fetch full info including description and keywords (takes time)"))
+        self.fullDesc.SetValue(False)
+        
+        self.search = SearchModuleWindow(parent = self.panel, showLabel = False)
+        self.search.SetSelection(2) 
+        
+        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)
+        repoSizer = wx.StaticBoxSizer(self.repoBox, wx.VERTICAL)
+        repo1Sizer = wx.BoxSizer(wx.HORIZONTAL)
+        repo1Sizer.Add(item = self.repo, proportion = 1,
+                      flag = wx.ALL | wx.ALIGN_CENTER_VERTICAL, border = 1)
+        repo1Sizer.Add(item = self.btnFetch, proportion = 0,
+                      flag = wx.ALL | wx.ALIGN_CENTER_VERTICAL, border = 1)
+        repoSizer.Add(item = repo1Sizer,
+                      flag = wx.EXPAND)
+        repoSizer.Add(item = self.fullDesc)
+        
+        findSizer = wx.StaticBoxSizer(self.findBox, wx.HORIZONTAL)
+        findSizer.Add(item = self.search, proportion = 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 = repoSizer, proportion = 0,
+                  flag = wx.ALL | wx.EXPAND, border = 3)
+        sizer.Add(item = findSizer, proportion = 0,
+                  flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | 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,
+                    'svnurl=' + self.repo.GetValue().strip()])
+        self.OnCloseWindow(None)
+        
+    def OnUpdateStatusBar(self, event):
+        """!Update statusbar text"""
+        element = self.search.GetSelection()
+        if not self.tree.IsLoaded():
+            self.SetStatusText(_("Fetch list of available extensions by clicking on 'Fetch' button"), 0)
+            return
+        
+        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(url = self.repo.GetValue().strip(), full = self.fullDesc.IsChecked())
+        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)
+        self._loaded = False
+        
+    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, url, full = False):
+        """!Load list of extensions"""
+        self.DeleteAllItems()
+        self.root = self.AddRoot(_("Menu tree"))
+        self._initTree()
+        
+        if full:
+            flags = 'g'
+        else:
+            flags = 'l'
+        ret = gcmd.RunCommand('g.extension', read = True,
+                              svnurl = url,
+                              flags = flags, quiet = True)
+        if not ret:
+            return
+        
+        mdict = dict()
+        for line in ret.splitlines():
+            if full:
+                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
+            else:
+                prefix, name = line.strip().split('.', 1)
+                if not mdict.has_key(prefix):
+                    mdict[prefix] = dict()
+                
+                mdict[prefix][name] = { 'command' : prefix + '.' + name }
+        
+        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)
+        
+        self._loaded = True
+
+    def IsLoaded(self):
+        """Check if items are loaded"""
+        return self._loaded

Modified: grass/trunk/gui/wxpython/gui_modules/gmodeler.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/gmodeler.py	2010-05-09 21:06:48 UTC (rev 42203)
+++ grass/trunk/gui/wxpython/gui_modules/gmodeler.py	2010-05-10 09:01:04 UTC (rev 42204)
@@ -58,6 +58,8 @@
 from gcmd         import GMessage, GError
 from gdialogs     import ElementDialog, GetImageHandlers
 from preferences  import PreferencesBaseDialog, globalSettings as UserSettings
+from ghelp        import SearchModuleWindow
+
 from grass.script import core as grass
 
 class Model(object):
@@ -477,6 +479,7 @@
                 Debug.msg(4, "ModelFrame.OnModelSave(): filename=%s" % self.modelFile)
                 self.WriteModelFile(self.modelFile)
                 self.SetStatusText(_('File <%s> saved') % self.modelFile, 0)
+                self.SetTitle(self.baseTitle + " - " +  os.path.basename(self.modelFile))
         elif not self.modelFile:
             self.OnModelSaveAs(None)
         
@@ -1530,37 +1533,20 @@
         self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
         
         self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
-
-        self.findBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
-                                    label=" %s " % _("Find module(s) by"))
+        
         self.cmdBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
                                    label=" %s " % _("Command"))
         
-        self.searchBy = wx.Choice(parent = self.panel, id = wx.ID_ANY,
-                                  choices = [_("description"),
-                                             _("keywords")])
-        self.searchBy.SetSelection(0)
-        self.search = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY,
-                                  value = "", size = (-1, 25))
-        self.searchTip  = menuform.StaticWrapText(parent = self.panel, id = wx.ID_ANY,
-                                                  size = (-1, 35))
-        
-        self.searchChoice = wx.Choice(parent = self.panel, id = wx.ID_ANY)
-        
         self.cmd_prompt = prompt.GPromptSTC(parent = self)
-
+        self.search = SearchModuleWindow(parent = self.panel, cmdPrompt = self.cmd_prompt)
+        
         # get commands
         items = self.cmd_prompt.GetCommandItems()
-        self.searchTip.SetLabel(_("%d modules found") % len(items))
-        self.searchChoice.SetItems(items)
         
         self.btnCancel = wx.Button(self.panel, wx.ID_CANCEL)
         self.btnOk     = wx.Button(self.panel, wx.ID_OK)
         self.btnOk.SetDefault()
         
-        self.search.Bind(wx.EVT_TEXT, self.OnSearchModule)
-        self.searchChoice.Bind(wx.EVT_CHOICE, self.OnSelectModule)
-        
         self._layout()
         
         self.SetSize((500, 275))
@@ -1570,31 +1556,12 @@
         btnSizer.AddButton(self.btnCancel)
         btnSizer.AddButton(self.btnOk)
         btnSizer.Realize()
-
-        findSizer = wx.StaticBoxSizer(self.findBox, wx.HORIZONTAL)
-        gridSizer = wx.GridBagSizer(hgap = 3, vgap = 3)
-        gridSizer.AddGrowableCol(1)
-
-        cmdSizer = wx.StaticBoxSizer(self.cmdBox, wx.VERTICAL)
         
-        gridSizer.Add(item = self.searchBy,
-                      flag=wx.ALIGN_CENTER_VERTICAL, pos = (0, 0))
-        gridSizer.Add(item = self.search,
-                      flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, pos = (0, 1))
-        gridSizer.Add(item = self.searchTip,
-                      flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, pos = (1, 0), span = (1, 2))
-        gridSizer.Add(item = self.searchChoice,
-                      flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, pos = (2, 0), span = (1, 2))
-        findSizer.Add(item = gridSizer, proportion = 1)
-        
-        cmdSizer.Add(item=self.cmd_prompt, proportion=1,
-                      flag=wx.EXPAND | wx.ALL, border=1)
-        
         mainSizer = wx.BoxSizer(wx.VERTICAL)
-        mainSizer.Add(item=findSizer, proportion=0,
-                      flag=wx.EXPAND | wx.ALL, border=5)
-        mainSizer.Add(item=cmdSizer, proportion=1,
-                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
+        mainSizer.Add(item=self.search, proportion=0,
+                      flag=wx.EXPAND | wx.ALL, border=3)
+        mainSizer.Add(item=self.cmd_prompt, proportion=1,
+                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, border=3)
         mainSizer.Add(item=btnSizer, proportion=0,
                       flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
         
@@ -1619,53 +1586,7 @@
             cmd = shlex.split(utils.EncodeString((line)))
             
         return cmd
-
-    def OnSearchModule(self, event):
-        """!Search module by keywords or description"""
-        text = event.GetString()
-        if not text:
-            self.cmd_prompt.SetFilter(None)
-            return
-        
-        modules = dict()
-        iFound = 0
-        for module, data in self.cmd_prompt.moduleDesc.iteritems():
-            found = False
-            if self.searchBy.GetSelection() == 0: # -> description
-                if text in data['desc']:
-                    found = True
-            else: # -> keywords
-                if self.cmd_prompt.CheckKey(text, data['keywords']):
-                    found = True
-
-            if found:
-                iFound += 1
-                try:
-                    group, name = module.split('.')
-                except ValueError:
-                    continue # TODO
-                
-                if not modules.has_key(group):
-                    modules[group] = list()
-                modules[group].append(name)
-
-        self.cmd_prompt.SetFilter(modules)
-        self.searchTip.SetLabel(_("%d modules found") % iFound)
-        self.searchChoice.SetItems(self.cmd_prompt.GetCommandItems())
-        
-    def OnSelectModule(self, event):
-        """!Module selected from choice, update command prompt"""
-        cmd  = event.GetString().split(' ', 1)[0]
-        text = cmd + ' '
-        pos = len(text)
-        self.cmd_prompt.SetText(text)
-        self.cmd_prompt.SetSelectionStart(pos)
-        self.cmd_prompt.SetCurrentPos(pos)
-        self.cmd_prompt.SetFocus()
-        
-        desc = self.cmd_prompt.GetCommandDesc(cmd)
-        self.searchTip.SetLabel(desc)
-                                
+    
     def OnOk(self, event):
         self.btnOk.SetFocus()
         

Modified: grass/trunk/gui/wxpython/gui_modules/goutput.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/goutput.py	2010-05-09 21:06:48 UTC (rev 42203)
+++ grass/trunk/gui/wxpython/gui_modules/goutput.py	2010-05-10 09:01:04 UTC (rev 42204)
@@ -40,7 +40,7 @@
 
 from debug       import Debug
 from preferences import globalSettings as UserSettings
-from help        import SearchModuleWindow
+from ghelp       import SearchModuleWindow
 
 wxCmdOutput,   EVT_CMD_OUTPUT   = NewEvent()
 wxCmdProgress, EVT_CMD_PROGRESS = NewEvent()
@@ -186,9 +186,10 @@
         self.Bind(EVT_CMD_DONE, self.OnCmdDone)
         
         # search & command prompt
-        self.search = SearchModuleWindow(parent = self.panelPrompt)
-        
         self.cmd_prompt = prompt.GPromptSTC(parent = self)
+                
+        self.search = SearchModuleWindow(parent = self.panelPrompt, cmdPrompt = self.cmd_prompt)
+        
         if self.parent.GetName() != 'LayerManager':
             self.search.Hide()
             self.cmd_prompt.Hide()
@@ -227,8 +228,6 @@
         self.btn_abort.Bind(wx.EVT_BUTTON,         self.OnCmdAbort)
         self.btn_abort.Bind(EVT_CMD_ABORT,         self.OnCmdAbort)
         
-        self.search.Bind(wx.EVT_TEXT,              self.OnSearchModule)
-        
         self.__layout()
         
     def __layout(self):
@@ -244,7 +243,7 @@
         
         if self.search.IsShown():
             PromptSizer.Add(item=self.search, proportion=0,
-                            flag=wx.EXPAND | wx.ALL, border=1)
+                            flag=wx.EXPAND | wx.ALL, border=3)
         PromptSizer.Add(item=self.cmd_prompt, proportion=1,
                         flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, border=3)
         
@@ -542,39 +541,7 @@
     def GetCmd(self):
         """!Get running command or None"""
         return self.requestQ.get()
-
-    def OnSearchModule(self, event):
-        """!Search module by keywords or description"""
-        text = event.GetString()
-        if not text:
-            self.cmd_prompt.SetFilter(None)
-            return
-        
-        modules = dict()
-        iFound = 0
-        for module, data in self.cmd_prompt.moduleDesc.iteritems():
-            found = False
-            if self.search.GetSelection() == 'description': # -> description
-                if text in data['desc']:
-                    found = True
-            else: # -> keywords
-                if self.cmd_prompt.CheckKey(text, data['keywords']):
-                    found = True
-
-            if found:
-                iFound += 1
-                try:
-                    group, name = module.split('.')
-                except ValueError:
-                    continue # TODO
-                
-                if not modules.has_key(group):
-                    modules[group] = list()
-                modules[group].append(name)
-        
-        self.parent.statusbar.SetStatusText(_("%d modules found") % iFound)
-        self.cmd_prompt.SetFilter(modules)
-        
+    
     def OnCmdOutput(self, event):
         """!Print command output"""
         message = event.text

Deleted: grass/trunk/gui/wxpython/gui_modules/help.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/help.py	2010-05-09 21:06:48 UTC (rev 42203)
+++ grass/trunk/gui/wxpython/gui_modules/help.py	2010-05-10 09:01:04 UTC (rev 42204)
@@ -1,928 +0,0 @@
-"""!
- at package help.py
-
- at brief Help window
-
-Classes:
- - HelpWindow
- - 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
-(>=v2). Read the file COPYING that comes with GRASS for details.
-
- at author Martin Landa <landa.martin gmail.com>
-"""
-
-import os
-
-import wx
-try:
-    import wx.lib.agw.customtreectrl as CT
-#    import wx.lib.agw.hyperlink as hl
-except ImportError:
-    import wx.lib.customtreectrl as CT
-#    import wx.lib.hyperlink as hl
-import wx.lib.flatnotebook as FN
-import  wx.lib.scrolledpanel as scrolled
-
-import menudata
-import gcmd
-import globalvar
-
-class HelpWindow(wx.Frame):
-    """!GRASS Quickstart help window"""
-    def __init__(self, parent, id, title, size, file):
-
-        wx.Frame.__init__(self, parent=parent, id=id, title=title, size=size)
-
-        sizer = wx.BoxSizer(wx.VERTICAL)
-
-        # text
-        helpFrame = wx.html.HtmlWindow(parent=self, id=wx.ID_ANY)
-        helpFrame.SetStandardFonts (size = 10)
-        helpFrame.SetBorders(10)
-        wx.InitAllImageHandlers()
-
-        helpFrame.LoadFile(file)
-        self.Ok = True
-
-        sizer.Add(item=helpFrame, proportion=1, flag=wx.EXPAND)
-
-        self.SetAutoLayout(True)
-        self.SetSizer(sizer)
-        #        sizer.Fit(self)
-        #        sizer.SetSizeHints(self)
-        self.Layout()
-
-class SearchModuleWindow(wx.Panel):
-    """!Search module window (used in MenuTreeWindow)"""
-    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 = { _('description') : 'description',
-                             _('command')     : 'command',
-                             _('keywords')    : 'keywords' }
-        
-        self.searchBy = wx.Choice(parent = self, id = wx.ID_ANY,
-                                  choices = [_('description'),
-                                             _('keywords'),
-                                             _('command')])
-        self.searchBy.SetSelection(0)
-        
-        self.search = wx.TextCtrl(parent = self, id = wx.ID_ANY,
-                                  value = "", size = (-1, 25),
-                                  style = wx.TE_PROCESS_ENTER)
-        
-        self._layout()
-
-    def _layout(self):
-        """!Do layout"""
-                # search
-        sizer = wx.BoxSizer(wx.HORIZONTAL)
-        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)
-        sizer.Add(item = self.search, proportion = 1,
-                  flag = wx.EXPAND | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL,
-                  border = 5)
-        
-        self.SetSizer(sizer)
-        sizer.Fit(self)
-
-    def GetSelection(self):
-        """!Get selected element"""
-        selection = self.searchBy.GetStringSelection()
-        
-        return self._searchDict[selection]
-
-    def SetSelection(self, i):
-        """!Set selection element"""
-        self.searchBy.SetSelection(i)
-        
-class MenuTreeWindow(wx.Panel):
-    """!Show menu tree"""
-    def __init__(self, parent, id = wx.ID_ANY, **kwargs):
-        self.parent = parent # LayerManager
-        
-        wx.Panel.__init__(self, parent = parent, id = id, **kwargs)
-        
-        self.dataBox = wx.StaticBox(parent = self, id = wx.ID_ANY,
-                                    label=" %s " % _("Menu tree (double-click to run command)"))
-        # tree
-        self.tree = MenuTree(parent = self, data = menudata.ManagerData())
-        self.tree.Load()
-
-        # search widget
-        self.search = SearchModuleWindow(parent = self)
-        
-        # buttons
-        self.btnRun   = wx.Button(self, id = wx.ID_OK, label = _("Run"))
-        self.btnRun.SetToolTipString(_("Run selected command"))
-        self.btnRun.Enable(False)
-        
-        # bindings
-        self.btnRun.Bind(wx.EVT_BUTTON,            self.OnRun)
-        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()
-        
-        self.search.SetFocus()
-        
-    def _layout(self):
-        """!Do dialog layout"""
-        sizer = wx.BoxSizer(wx.VERTICAL)
-        
-        # body
-        dataSizer = wx.StaticBoxSizer(self.dataBox, wx.HORIZONTAL)
-        dataSizer.Add(item = self.tree, proportion =1,
-                      flag = wx.EXPAND)
-        
-        # buttons
-        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
-        btnSizer.Add(item = self.btnRun, proportion = 0,
-                     flag = wx.LEFT | wx.RIGHT, border = 5)
-        
-        sizer.Add(item = dataSizer, proportion = 1,
-                  flag = wx.EXPAND | wx.ALL, border = 5)
-
-        sizer.Add(item = self.search, proportion=0,
-                  flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
-        
-        sizer.Add(item = btnSizer, proportion=0,
-                  flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
-        
-        sizer.Fit(self)
-        sizer.SetSizeHints(self)
-        
-        self.SetSizer(sizer)
-        
-        self.Fit()
-        self.SetAutoLayout(True)        
-        self.Layout()
-        
-    def OnCloseWindow(self, event):
-        """!Close window"""
-        self.Destroy()
-        
-    def OnRun(self, event):
-        """!Run selected command"""
-        if not self.tree.GetSelected():
-            return # should not happen
-        
-        data = self.tree.GetPyData(self.tree.GetSelected())
-        if not data:
-            return
-
-        handler = 'self.parent.' + data['handler'].lstrip('self.')
-        if data['handler'] == 'self.OnXTerm':
-            wx.MessageBox(parent = self,
-                          message = _('You must run this command from the menu or command line',
-                                      'This command require an XTerm'),
-                          caption = _('Message'), style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
-        elif data['command']:
-            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)"""
-        item = event.GetItem()
-        if not item or not item.IsOk():
-            return
-        
-        data = self.tree.GetPyData(item)
-        if not data or not data.has_key('command'):
-            return
-        
-        self.tree.itemSelected = item
-        
-        self.OnRun(None)
-        
-    def OnItemSelected(self, event):
-        """!Item selected"""
-        item = event.GetItem()
-        if not item or not item.IsOk():
-            return
-        
-        data = self.tree.GetPyData(item)
-        if not data or not data.has_key('command'):
-            return
-        
-        if data['command']:
-            label = data['command'] + ' -- ' + data['description']
-        else:
-            label = data['description']
-        
-        self.parent.SetStatusText(label, 0)
-        
-    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.parent.SetStatusText(_("%d items match") % nItems, 0)
-        else:
-            self.parent.SetStatusText("", 0)
-        
-        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 
-
-        @param element element index (see self.searchBy)
-        @param value
-
-        @return list of found tree items
-        """
-        items = list()
-        if not value:
-            return 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):
-        """!Search items (used by SearchItems)
-        
-        @param item reference item
-        @param listOfItems list of found items
-        """
-        while item and item.IsOk():
-            subItem = self.GetFirstChild(item)[0]
-            if subItem:
-                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.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, **kwargs):
-        self.parent   = parent
-        self.menudata = data
-
-        super(MenuTree, self).__init__(parent, **kwargs)
-        
-    def Load(self, data = None):
-        """!Load menu data tree
-
-        @param data menu data (None to use self.menudata)
-        """
-        if not data:
-            data = self.menudata
-        
-        self.itemsMarked = [] # list of marked items
-        for eachMenuData in data.GetMenu():
-            for label, items in eachMenuData:
-                item = self.AppendItem(parentId = self.root,
-                                       text = label.replace('&', ''))
-                self.__AppendItems(item, items)
-        
-    def __AppendItems(self, item, data):
-        """!Append items into tree (used by Load()
-        
-        @param item tree item (parent)
-        @parent data menu data"""
-        for eachItem in data:
-            if len(eachItem) == 2:
-                if eachItem[0]:
-                    itemSub = self.AppendItem(parentId = item,
-                                    text = eachItem[0])
-                self.__AppendItems(itemSub, eachItem[1])
-            else:
-                if eachItem[0]:
-                    itemNew = self.AppendItem(parentId = item,
-                                              text = eachItem[0])
-                    
-                    data = { 'item'        : eachItem[0],
-                             'description' : eachItem[1],
-                             'handler'  : eachItem[2],
-                             'command'  : eachItem[3],
-                             'keywords' : eachItem[4] }
-                    
-                    self.SetPyData(itemNew, data)
-        
-class AboutWindow(wx.Frame):
-    def __init__(self, parent):
-        """!Create custom About Window
-
-        @todo improve styling
-        """
-        wx.Frame.__init__(self, parent=parent, id=wx.ID_ANY, size=(550,400), 
-                          title=_('About GRASS GIS'))
-        
-        panel = wx.Panel(parent = self, id = wx.ID_ANY)
-        
-        # icon
-        self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
-
-        # get version and web site
-        version, svn_gis_h_rev, svn_gis_h_date = gcmd.RunCommand('g.version',
-                                                                 flags = 'r',
-                                                                 read = True).splitlines()
-        
-        infoTxt = wx.Panel(parent = panel, id = wx.ID_ANY)
-        infoSizer = wx.BoxSizer(wx.VERTICAL)
-        infoGridSizer = wx.GridBagSizer(vgap=5, hgap=5)
-        infoGridSizer.AddGrowableCol(0)
-        infoGridSizer.AddGrowableCol(1)
-        logo = os.path.join(globalvar.ETCDIR, "gui", "icons", "grass.ico")
-        logoBitmap = wx.StaticBitmap(parent = infoTxt, id = wx.ID_ANY,
-                                     bitmap = wx.Bitmap(name = logo,
-                                                        type = wx.BITMAP_TYPE_ICO))
-        infoSizer.Add(item = logoBitmap, proportion = 0,
-                      flag = wx.ALL | wx.ALIGN_CENTER, border = 25)
-        
-        info = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
-                             label = version.replace('GRASS', 'GRASS GIS').strip() + '\n\n')
-        info.SetFont(wx.Font(13, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
-        infoSizer.Add(item = info, proportion = 0,
-                          flag = wx.BOTTOM | wx.ALIGN_CENTER, border = 15)
-
-        infoGridSizer.Add(item = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
-                                               label = _('Official GRASS site:')),
-                          pos = (0, 0),
-                          flag = wx.ALIGN_RIGHT)
-
-        infoGridSizer.Add(item = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
-                                               label = 'http://grass.osgeo.org'),
-                          pos = (0, 1),
-                          flag = wx.ALIGN_LEFT)
-
-        # infoGridSizer.Add(item = hl.HyperLinkCtrl(parent = self, id = wx.ID_ANY,
-        #                                           label = 'http://grass.osgeo.org',
-        #                                           URL = 'http://grass.osgeo.org'),
-        #                   pos = (0, 1),
-        #                   flag = wx.LEFT)
-        
-        infoGridSizer.Add(item = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
-                                               label = _('GIS Library Revision:')),
-                          pos = (2, 0),
-                          flag = wx.ALIGN_RIGHT)
-        
-        infoGridSizer.Add(item = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
-                                               label = svn_gis_h_rev.split(' ')[1] + ' (' +
-                                               svn_gis_h_date.split(' ')[1] + ')'),
-                          pos = (2, 1),
-                          flag = wx.ALIGN_LEFT)
-
-        infoSizer.Add(item = infoGridSizer,
-                      proportion = 1,
-                      flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL,
-                      border = 25)
-        
-        #
-        # create pages
-        #
-        copyrightwin = self.PageCopyright()
-        licensewin   = self.PageLicense()
-        authorwin    = self.PageCredit()
-        contribwin   = self.PageContributors()
-        transwin     = self.PageTranslators()
-
-        # create a flat notebook for displaying information about GRASS
-        nbstyle = FN.FNB_VC8 | \
-                FN.FNB_BACKGROUND_GRADIENT | \
-                FN.FNB_TABS_BORDER_SIMPLE | \
-                FN.FNB_NO_X_BUTTON
-        
-        aboutNotebook = FN.FlatNotebook(panel, id=wx.ID_ANY, style=nbstyle)
-        aboutNotebook.SetTabAreaColour(globalvar.FNPageColor)
-        
-        # make pages for About GRASS notebook
-        pg1 = aboutNotebook.AddPage(infoTxt,      text=_("Info"))
-        pg2 = aboutNotebook.AddPage(copyrightwin, text=_("Copyright"))
-        pg3 = aboutNotebook.AddPage(licensewin,   text=_("License"))
-        pg4 = aboutNotebook.AddPage(authorwin,    text=_("Authors"))
-        pg5 = aboutNotebook.AddPage(contribwin,   text=_("Contributors"))
-        pg5 = aboutNotebook.AddPage(transwin,     text=_("Translators"))
-        
-        wx.CallAfter(aboutNotebook.SetSelection, 0)
-        
-        # buttons
-        btnClose = wx.Button(parent = panel, id = wx.ID_CLOSE)
-        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
-        btnSizer.Add(item = btnClose, proportion = 0,
-                     flag = wx.ALL | wx.ALIGN_RIGHT,
-                     border = 5)
-        # bindings
-        # self.aboutNotebook.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.OnAGPageChanged)
-        btnClose.Bind(wx.EVT_BUTTON, self.OnCloseWindow)
-
-        infoTxt.SetSizer(infoSizer)
-        infoSizer.Fit(infoTxt)
-        
-        sizer = wx.BoxSizer(wx.VERTICAL)
-        sizer.Add(item=aboutNotebook, proportion=1,
-                  flag=wx.EXPAND | wx.ALL, border=1)
-        sizer.Add(item=btnSizer, proportion=0,
-                  flag=wx.ALL | wx.ALIGN_RIGHT, border=1)
-        panel.SetSizer(sizer)
-        self.Layout()
-    
-    def PageCopyright(self):
-        """Copyright information"""
-        copyfile = os.path.join(os.getenv("GISBASE"), "COPYING")
-        if os.path.exists(copyfile):
-            copyrightFile = open(copyfile, 'r')
-            copytext = copyrightFile.read()
-            copyrightFile.close()
-        else:
-            copytext = _('%s file missing') % 'COPYING'
-        
-        # put text into a scrolling panel
-        copyrightwin = scrolled.ScrolledPanel(self, id=wx.ID_ANY, 
-                                              size=wx.DefaultSize,
-                                              style = wx.TAB_TRAVERSAL | wx.SUNKEN_BORDER)
-        copyrighttxt = wx.StaticText(copyrightwin, id=wx.ID_ANY, label=copytext)
-        copyrightwin.SetAutoLayout(True)
-        copyrightwin.sizer = wx.BoxSizer(wx.VERTICAL)
-        copyrightwin.sizer.Add(item=copyrighttxt, proportion=1,
-                               flag=wx.EXPAND | wx.ALL, border=3)
-        copyrightwin.SetSizer(copyrightwin.sizer)
-        copyrightwin.Layout()
-        copyrightwin.SetupScrolling()
-        
-        return copyrightwin
-    
-    def PageLicense(self):
-        """Licence about"""
-        licfile = os.path.join(os.getenv("GISBASE"), "GPL.TXT")
-        if os.path.exists(licfile):
-            licenceFile = open(licfile, 'r')
-            license = ''.join(licenceFile.readlines())
-            licenceFile.close()
-        else:
-            license = _('%s file missing') % 'GPL.TXT'
-        # put text into a scrolling panel
-        licensewin = scrolled.ScrolledPanel(self, id=wx.ID_ANY, 
-                                            style = wx.TAB_TRAVERSAL | wx.SUNKEN_BORDER)
-        licensetxt = wx.StaticText(licensewin, id=wx.ID_ANY, label=license)
-        licensewin.SetAutoLayout(True)
-        licensewin.sizer = wx.BoxSizer(wx.VERTICAL)
-        licensewin.sizer.Add(item=licensetxt, proportion=1,
-                flag=wx.EXPAND | wx.ALL, border=3)
-        licensewin.SetSizer(licensewin.sizer)
-        licensewin.Layout()
-        licensewin.SetupScrolling()
-        
-        return licensewin
-    
-    def PageCredit(self):
-        """Credit about"""
-                # credits
-        authfile = os.path.join(os.getenv("GISBASE"), "AUTHORS")
-        if os.path.exists(authfile):
-            authorsFile = open(authfile, 'r')
-            authors = unicode(''.join(authorsFile.readlines()), "utf-8")
-            authorsFile.close()
-        else:
-            authors = _('%s file missing') % 'AUTHORS'
-        authorwin = scrolled.ScrolledPanel(self, id=wx.ID_ANY, 
-                                           style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
-        authortxt = wx.StaticText(authorwin, id=wx.ID_ANY, label=authors)
-        authorwin.SetAutoLayout(1)
-        authorwin.SetupScrolling()
-        authorwin.sizer = wx.BoxSizer(wx.VERTICAL)
-        authorwin.sizer.Add(item=authortxt, proportion=1,
-                flag=wx.EXPAND | wx.ALL, border=3)
-        authorwin.SetSizer(authorwin.sizer)
-        authorwin.Layout()      
-        
-        return authorwin
-
-    def PageContributors(self):
-        """Contributors info"""
-        contribfile = os.path.join(os.getenv("GISBASE"), "contributors.csv")
-        if os.path.exists(contribfile):
-            contribFile = open(contribfile, 'r')
-            contribs = list()
-            for line in contribFile.readlines():
-                cvs_id, name, email, country, osgeo_id, rfc2_agreed = line.split(',')
-                contribs.append((name, email, country, osgeo_id))
-            contribs[0] = (_('Name'), _('E-mail'), _('Country'), _('OSGeo_ID'))
-            contribFile.close()
-        else:
-            contribs = None
-        
-        contribwin = scrolled.ScrolledPanel(self, id=wx.ID_ANY, 
-                                           style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
-        contribwin.SetAutoLayout(1)
-        contribwin.SetupScrolling()
-        contribwin.sizer = wx.BoxSizer(wx.VERTICAL)
-        
-        if not contribs:
-            contribtxt = wx.StaticText(contribwin, id=wx.ID_ANY,
-                                       label=_('%s file missing') % 'contibutors.csv')
-            contribwin.sizer.Add(item=contribtxt, proportion=1,
-                                 flag=wx.EXPAND | wx.ALL, border=3)
-        else:
-            contribBox = wx.FlexGridSizer(cols=4, vgap=5, hgap=5)
-            for developer in contribs:
-                for item in developer:
-                    contribBox.Add(item = wx.StaticText(parent = contribwin, id = wx.ID_ANY,
-                                                        label = item))
-            contribwin.sizer.Add(item=contribBox, proportion=1,
-                                 flag=wx.EXPAND | wx.ALL, border=3)
-        
-        contribwin.SetSizer(contribwin.sizer)
-        contribwin.Layout()      
-        
-        return contribwin
-
-    def PageTranslators(self):
-        """Translators info"""
-        translatorsfile = os.path.join(os.getenv("GISBASE"), "translators.csv")
-        if os.path.exists(translatorsfile):
-            translatorsFile = open(translatorsfile, 'r')
-            translators = dict()
-            for line in translatorsFile.readlines()[1:]:
-                name, email, languages = line.rstrip('\n').split(',')
-                for language in languages.split(' '):
-                    if not translators.has_key(language):
-                        translators[language] = list()
-                    translators[language].append((name, email))
-            translatorsFile.close()
-        else:
-            translators = None
-        
-        translatorswin = scrolled.ScrolledPanel(self, id=wx.ID_ANY, 
-                                           style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
-        translatorswin.SetAutoLayout(1)
-        translatorswin.SetupScrolling()
-        translatorswin.sizer = wx.BoxSizer(wx.VERTICAL)
-        
-        if not translators:
-            translatorstxt = wx.StaticText(translatorswin, id=wx.ID_ANY,
-                                           label=_('%s file missing') % 'translators.csv')
-            translatorswin.sizer.Add(item=translatorstxt, proportion=1,
-                                 flag=wx.EXPAND | wx.ALL, border=3)
-        else:
-            translatorsBox = wx.FlexGridSizer(cols=3, vgap=5, hgap=5)
-            languages = translators.keys()
-            languages.sort()
-            translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
-                                                    label = _('Name')))
-            translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
-                                                    label = _('E-mail')))
-            translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
-                                                    label = _('Language')))
-            for lang in languages:
-                for translator in translators[lang]:
-                    name, email = translator
-                    translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
-                                                            label =  unicode(name, "utf-8")))
-                    translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
-                                                            label = email))
-                    translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
-                                                            label = lang))
-            
-            translatorswin.sizer.Add(item=translatorsBox, proportion=1,
-                                 flag=wx.EXPAND | wx.ALL, border=3)
-        
-        translatorswin.SetSizer(translatorswin.sizer)
-        translatorswin.Layout()      
-        
-        return translatorswin
-    
-    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.repoBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
-                                    label=" %s " % _("Repository"))
-        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.repo = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY,
-                                value = 'https://svn.osgeo.org/grass/grass-addons')
-        self.fullDesc = wx.CheckBox(parent = self.panel, id=wx.ID_ANY,
-                                    label = _("Fetch full info including description and keywords (takes time)"))
-        self.fullDesc.SetValue(False)
-        
-        self.search = SearchModuleWindow(parent = self.panel, showLabel = False)
-        self.search.SetSelection(2) 
-        
-        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)
-        repoSizer = wx.StaticBoxSizer(self.repoBox, wx.VERTICAL)
-        repo1Sizer = wx.BoxSizer(wx.HORIZONTAL)
-        repo1Sizer.Add(item = self.repo, proportion = 1,
-                      flag = wx.ALL | wx.ALIGN_CENTER_VERTICAL, border = 1)
-        repo1Sizer.Add(item = self.btnFetch, proportion = 0,
-                      flag = wx.ALL | wx.ALIGN_CENTER_VERTICAL, border = 1)
-        repoSizer.Add(item = repo1Sizer,
-                      flag = wx.EXPAND)
-        repoSizer.Add(item = self.fullDesc)
-        
-        findSizer = wx.StaticBoxSizer(self.findBox, wx.HORIZONTAL)
-        findSizer.Add(item = self.search, proportion = 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 = repoSizer, proportion = 0,
-                  flag = wx.ALL | wx.EXPAND, border = 3)
-        sizer.Add(item = findSizer, proportion = 0,
-                  flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | 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,
-                    'svnurl=' + self.repo.GetValue().strip()])
-        self.OnCloseWindow(None)
-        
-    def OnUpdateStatusBar(self, event):
-        """!Update statusbar text"""
-        element = self.search.GetSelection()
-        if not self.tree.IsLoaded():
-            self.SetStatusText(_("Fetch list of available extensions by clicking on 'Fetch' button"), 0)
-            return
-        
-        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(url = self.repo.GetValue().strip(), full = self.fullDesc.IsChecked())
-        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)
-        self._loaded = False
-        
-    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, url, full = False):
-        """!Load list of extensions"""
-        self.DeleteAllItems()
-        self.root = self.AddRoot(_("Menu tree"))
-        self._initTree()
-        
-        if full:
-            flags = 'g'
-        else:
-            flags = 'l'
-        ret = gcmd.RunCommand('g.extension', read = True,
-                              svnurl = url,
-                              flags = flags, quiet = True)
-        if not ret:
-            return
-        
-        mdict = dict()
-        for line in ret.splitlines():
-            if full:
-                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
-            else:
-                prefix, name = line.strip().split('.', 1)
-                if not mdict.has_key(prefix):
-                    mdict[prefix] = dict()
-                
-                mdict[prefix][name] = { 'command' : prefix + '.' + name }
-        
-        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)
-        
-        self._loaded = True
-
-    def IsLoaded(self):
-        """Check if items are loaded"""
-        return self._loaded



More information about the grass-commit mailing list