[GRASS-SVN] r38973 - in grass/trunk/gui/wxpython: . gui_modules xml

svn_grass at osgeo.org svn_grass at osgeo.org
Fri Sep 4 13:37:06 EDT 2009


Author: martinl
Date: 2009-09-04 13:37:06 -0400 (Fri, 04 Sep 2009)
New Revision: 38973

Modified:
   grass/trunk/gui/wxpython/gui_modules/gdialogs.py
   grass/trunk/gui/wxpython/gui_modules/help.py
   grass/trunk/gui/wxpython/gui_modules/menudata.py
   grass/trunk/gui/wxpython/wxgui.py
   grass/trunk/gui/wxpython/xml/menudata.xml
Log:
wxGUI: Menu tree window implemnted


Modified: grass/trunk/gui/wxpython/gui_modules/gdialogs.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/gdialogs.py	2009-09-04 17:30:26 UTC (rev 38972)
+++ grass/trunk/gui/wxpython/gui_modules/gdialogs.py	2009-09-04 17:37:06 UTC (rev 38973)
@@ -975,7 +975,7 @@
         self.SetMinSize((globalvar.DIALOG_GSELECT_SIZE[0] + 175, 300))
         width = self.GetSize()[0]
         self.list.SetColumnWidth(col=1, width=width/2 - 50)
-
+        
     def OnCancel(self, event=None):
         """!Close dialog"""
         self.Close()

Modified: grass/trunk/gui/wxpython/gui_modules/help.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/help.py	2009-09-04 17:30:26 UTC (rev 38972)
+++ grass/trunk/gui/wxpython/gui_modules/help.py	2009-09-04 17:37:06 UTC (rev 38973)
@@ -7,6 +7,7 @@
 
 Classes:
  - HelpWindow
+ - MenuTreeWindow
 
 (C) 2008-2009 by the GRASS Development Team
 
@@ -18,7 +19,11 @@
 """
 
 import wx
+import wx.lib.customtreectrl as CT
 
+import menudata
+import gcmd
+
 class HelpWindow(wx.Frame):
     """!GRASS Quickstart help window"""
     def __init__(self, parent, id, title, size, file):
@@ -43,3 +48,291 @@
         #        sizer.Fit(self)
         #        sizer.SetSizeHints(self)
         self.Layout()
+
+class MenuTreeWindow(wx.Frame):
+    """!Show menu tree"""
+    def __init__(self, parent, id = wx.ID_ANY, title = _("Menu tree window"), **kwargs):
+        self.parent = parent # LayerManager
+        
+        wx.Frame.__init__(self, parent = parent, id = id, title = title, **kwargs)
+
+        self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
+        
+        # tree
+        self.tree = MenuTree(parent = self.panel, data = menudata.Data())
+        self.tree.Load()
+        
+        self.searchDict = { _('label')    : 'label', # i18n workaround
+                            _('help')     : 'help',
+                            _('command')  : 'command',
+                            _('keywords') : 'keywords' }
+        # search
+        self.searchBy = wx.Choice(parent = self.panel, id = wx.ID_ANY,
+                                  choices = [_('label'),
+                                             _('help'),
+                                             _('command'),
+                                             _('keywords')])
+        self.search = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY,
+                                  value = "", size = (-1, 25),
+                                  style = wx.TE_PROCESS_ENTER)
+        
+        # statusbar
+        self.statusbar = self.CreateStatusBar(number=1)
+
+        # close on run
+        self.closeOnRun = wx.CheckBox(parent = self.panel, id = wx.ID_ANY,
+                                      label = _("Close dialog on run"))
+        self.closeOnRun.SetValue(True)
+        
+        # buttons
+        self.btnRun   = wx.Button(self.panel, id = wx.ID_OK, label = _("Run"))
+        self.btnRun.SetToolTipString(_("Run selected command"))
+        self.btnRun.Enable(False)
+        self.btnClose = wx.Button(self.panel, id = wx.ID_CLOSE)
+        self.btnClose.SetToolTipString(_("Close dialog"))
+
+        # bindings
+        self.btnClose.Bind(wx.EVT_BUTTON,          self.OnCloseWindow)
+        self.btnRun.Bind(wx.EVT_BUTTON,            self.OnRun)
+        self.search.Bind(wx.EVT_TEXT_ENTER,        self.OnShowItem)
+        self.search.Bind(wx.EVT_TEXT,              self.OnUpdateStatusBar)
+        self.tree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnItemActivated)
+        self.tree.Bind(wx.EVT_TREE_SEL_CHANGED,    self.OnItemSelected)
+
+        self.__Layout()
+
+        self.search.SetFocus()
+        
+    def __Layout(self):
+        """!Do dialog layout"""
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        
+        # body
+        dataBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
+                               label=" %s " % _("Menu tree (double-click to run command)"))
+        
+        dataSizer = wx.StaticBoxSizer(dataBox, wx.HORIZONTAL)
+        dataSizer.Add(item = self.tree, proportion =1,
+                      flag = wx.EXPAND)
+        
+        # search
+        searchSizer = wx.BoxSizer(wx.HORIZONTAL)
+        searchSizer.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
+                                             label = _("Search:")),
+                        proportion = 0,
+                        flag = wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
+                        border = 3)
+        searchSizer.Add(item = self.searchBy, proportion = 0,
+                        flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT | wx.RIGHT,
+                        border = 5)
+        searchSizer.Add(item = self.search, proportion = 1,
+                        flag = wx.EXPAND | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL,
+                        border = 5)
+        
+        # buttons
+        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
+        btnSizer.Add(item = self.btnRun, proportion = 0,
+                     flag = wx.LEFT | wx.RIGHT, border = 5)
+        btnSizer.Add(item = self.btnClose, 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 = searchSizer, 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.Add(item = self.closeOnRun, proportion=0,
+                  flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
+        
+        self.panel.SetAutoLayout(True)
+        self.panel.SetSizer(sizer)
+        sizer.Fit(self.panel)
+        
+        self.Layout()
+        self.SetSize((530, 370))
+        
+    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 or not data.has_key('command'):
+            return
+        
+        gcmd.RunCommand(data['command'])
+        
+        if self.closeOnRun.IsChecked():
+            self.OnCloseWindow(None)
+        
+    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
+        
+        self.statusbar.SetStatusText(data['command'] + ' -- ' + data['help'], 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
+
+    def OnUpdateStatusBar(self, event):
+        """!Update statusbar text"""
+        element = self.searchDict[self.searchBy.GetStringSelection()]
+        self.tree.itemsMarked = self.SearchItems(element = element,
+                                                 value = event.GetString())
+        self.tree.itemSelected = None
+        
+        nItems = len(self.tree.itemsMarked)
+        if event.GetString():
+            self.statusbar.SetStatusText(_("%d items match") % nItems, 0)
+        else:
+            self.statusbar.SetStatusText("", 0)
+        
+        if nItems > 0:
+            self.tree.itemSelected = self.tree.itemsMarked[0]
+            self.btnRun.Enable()
+        else:
+            self.btnRun.Enable(False)
+        
+        event.Skip()
+        
+    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.tree.GetFirstChild(self.tree.root)[0]
+        self.__ProcessItem(item, element, value, items)
+        
+        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.tree.GetFirstChild(item)[0]
+            if subItem:
+                self.__ProcessItem(subItem, element, value, listOfItems)
+            data = self.tree.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):
+    """!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):
+        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
+        
+    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)
+                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 = { 'label'    : eachItem[0],
+                             'help'     : eachItem[1],
+                             'handler'  : eachItem[2],
+                             'command'  : eachItem[3],
+                             'keywords' : eachItem[4] }
+                    
+                    self.SetPyData(itemNew, data)
+        
+    def GetSelected(self):
+        """!Get selected item"""
+        return self.itemSelected

Modified: grass/trunk/gui/wxpython/gui_modules/menudata.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/menudata.py	2009-09-04 17:30:26 UTC (rev 38972)
+++ grass/trunk/gui/wxpython/gui_modules/menudata.py	2009-09-04 17:37:06 UTC (rev 38973)
@@ -5,6 +5,7 @@
 
 Classes:
  - Data
+ - MenuTree
 
 (C) 2007-2009 by the GRASS Development Team
 This program is free software under the GNU General Public
@@ -33,17 +34,22 @@
 
     def getMenuItem(self, mi):
 	if mi.tag == 'separator':
-	    return ('', '', '', '')
+	    return ('', '', '', '', '')
 	elif mi.tag == 'menuitem':
-	    label   = _(mi.find('label').text)
-	    help    = _(mi.find('help').text)
-	    handler = mi.find('handler').text
-	    gcmd    = mi.find('command')
+	    label    = _(mi.find('label').text)
+	    help     = _(mi.find('help').text)
+	    handler  = mi.find('handler').text
+	    gcmd     = mi.find('command')  # optional
+            keywords = mi.find('keywords') # optional
 	    if gcmd != None:
 		gcmd = gcmd.text
 	    else:
 		gcmd = ""
-	    return (label, help, handler, gcmd)
+            if keywords != None:
+                keywords = keywords.text
+            else:
+                keywords = ""
+	    return (label, help, handler, gcmd, keywords)
 	elif mi.tag == 'menu':
 	    return self.getMenu(mi)
 	else:
@@ -64,12 +70,40 @@
 	return self.getMenuData(self.tree.getroot())
 
     def PrintStrings(self, fh):
+        """!Print menu strings to file (used for localization)
+
+        @param fh file descriptor"""
 	fh.write('menustrings = [\n')
 	for node in self.tree.getiterator():
 	    if node.tag in ['label', 'help']:
 		fh.write('     _(%r),\n' % node.text)
 	fh.write('    \'\']\n')
 
+    def PrintTree(self, fh):
+        """!Print menu tree to file
+
+        @param fh file descriptor"""
+        level = 0
+        for eachMenuData in self.GetMenu():
+            for label, items in eachMenuData:
+                print >> fh, '-', label
+                self.__PrintTreeItems(fh, level + 1, items)
+
+    def __PrintTreeItems(self, fh, level, menuData):
+        """!Print menu tree items to file (used by PrintTree)
+
+        @param fh file descriptor
+        @param level menu level
+        @param menuData menu data to print out"""
+        for eachItem in menuData:
+            if len(eachItem) == 2:
+                if eachItem[0]:
+                    print >> fh, ' ' * level, '-', eachItem[0]
+                self.__PrintTreeItems(fh, level + 1, eachItem[1])
+            else:
+                if eachItem[0]:
+                    print >> fh, ' ' * level, '-', eachItem[0]
+        
     def GetModules(self):
         """!Create dictionary of modules used to search module by
         keywords, description, etc."""
@@ -95,9 +129,16 @@
 
 if __name__ == "__main__":
     import sys
-    if len(sys.argv) < 2:
-        sys.exit(1)
+
+    # i18N
+    import gettext
+    gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode=True)
     
-    Data(sys.argv[1]).PrintStrings(sys.stdout)
+    if len(sys.argv) > 1:
+        data = Data(sys.argv[1])
+    else:
+        data = Data()
     
+    data.PrintTree(sys.stdout)
+    
     sys.exit(0)

Modified: grass/trunk/gui/wxpython/wxgui.py
===================================================================
--- grass/trunk/gui/wxpython/wxgui.py	2009-09-04 17:30:26 UTC (rev 38972)
+++ grass/trunk/gui/wxpython/wxgui.py	2009-09-04 17:37:06 UTC (rev 38973)
@@ -87,8 +87,9 @@
 import gui_modules.colorrules as colorrules
 import gui_modules.ogc_services as ogc_services
 import gui_modules.prompt as prompt
-from   gui_modules.debug import Debug as Debug
-from   icons.icon import Icons as Icons
+from   gui_modules.debug import Debug
+from   gui_modules.help import MenuTreeWindow
+from   icons.icon import Icons
 
 UserSettings = preferences.globalSettings
 
@@ -230,7 +231,7 @@
         self.Bind(wx.EVT_MENU_HIGHLIGHT_ALL, self.OnMenuHighlight)
         return menu
 
-    def __createMenuItem(self, menu, label, help, handler, gcmd, kind=wx.ITEM_NORMAL):
+    def __createMenuItem(self, menu, label, help, handler, gcmd, keywords, kind = wx.ITEM_NORMAL):
         """!Creates menu items"""
 
         if not label:
@@ -475,7 +476,13 @@
                                             lchecked=True,
                                             lopacity=1.0,
                                             lcmd=['d.vect', 'map=%s' % name])
-            
+           
+    def OnMenuTree(self, event):
+        """!Show dialog with menu tree"""
+        dlg = MenuTreeWindow(self)
+        dlg.CentreOnScreen()
+        dlg.Show()
+    
     def OnAboutGRASS(self, event):
         """!Display 'About GRASS' dialog"""
         info = wx.AboutDialogInfo()

Modified: grass/trunk/gui/wxpython/xml/menudata.xml
===================================================================
--- grass/trunk/gui/wxpython/xml/menudata.xml	2009-09-04 17:30:26 UTC (rev 38972)
+++ grass/trunk/gui/wxpython/xml/menudata.xml	2009-09-04 17:37:06 UTC (rev 38973)
@@ -2697,20 +2697,27 @@
       <label>Help</label>
       <items>
 	<menuitem>
-	  <label>GRASS GIS help</label>
-	  <help>Display the HTML man pages of GRASS</help>
+	  <label>GRASS help</label>
+	  <help>Display the manual pages of GRASS</help>
 	  <keywords>general,manual,help</keywords>
           <handler>self.RunMenuCmd</handler>
 	  <command>g.manual -i</command>
 	</menuitem>
 	<menuitem>
-	  <label>GRASS GIS GUI help</label>
-	  <help>Display the HTML man pages of GRASS</help>
+	  <label>GUI help</label>
+	  <help>Display the manual pages of wxGUI</help>
 	  <keywords>general,manual,help</keywords>
           <handler>self.RunMenuCmd</handler>
 	  <command>g.manual wxGUI</command>
 	</menuitem>
+	<separator />
 	<menuitem>
+	  <label>Show menu tree</label>
+	  <help>Show menu tree in new window</help>
+          <handler>self.OnMenuTree</handler>
+	</menuitem>
+	<separator />
+	<menuitem>
 	  <label>About GRASS GIS</label>
 	  <help>About GRASS GIS</help>
 	  <handler>self.OnAboutGRASS</handler>



More information about the grass-commit mailing list