"""!
@package menudata.py
@brief Complex list for menu entries for wxGUI.
Classes:
- MenuData
- ManagerData
- ModelerData
- PsMapData
Usage:
@code
python menudata.py [action] [manager|modeler]
@endcode
where action:
- strings (default)
- tree
- commands
- dump
(C) 2007-2011 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.
@author Michael Barton (Arizona State University)
@author Yann Chemin
@author Martin Landa
@author Glynn Clements
@author Anna Kratochvilova
"""
import os
import sys
import pprint
try:
import xml.etree.ElementTree as etree
except ImportError:
import elementtree.ElementTree as etree # Python <= 2.4
import wx
if not os.getenv("GISBASE"):
sys.exit("GRASS is not running. Exiting...")
etcwxdir = os.path.join(os.getenv("GISBASE"), "etc", "gui", "wxpython")
class MenuData:
"""!Abstract menu data class"""
def __init__(self, filename):
self.tree = etree.parse(filename)
def _getMenuItem(self, mi):
"""!Get menu item
@param mi menu item instance
"""
if mi.tag == 'separator':
return ('', '', '', '', '')
elif mi.tag == 'menuitem':
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
shortcut = mi.find('shortcut') # optional
wxId = mi.find('id') # optional
if gcmd != None:
gcmd = gcmd.text
else:
gcmd = ""
if keywords != None:
keywords = keywords.text
else:
keywords = ""
if shortcut != None:
shortcut = shortcut.text
else:
shortcut = ""
if wxId != None:
wxId = eval('wx.' + wxId.text)
else:
wxId = wx.ID_ANY
return (label, help, handler, gcmd, keywords, shortcut, wxId)
elif mi.tag == 'menu':
return self._getMenu(mi)
else:
raise Exception(_("Unknow tag"))
def _getMenu(self, m):
"""!Get menu
@param m menu
@return label, menu items
"""
label = _(m.find('label').text)
items = m.find('items')
return (label, tuple(map(self._getMenuItem, items)))
def _getMenuBar(self, mb):
"""!Get menu bar
@param mb menu bar instance
@return menu items
"""
return tuple(map(self._getMenu, mb.findall('menu')))
def _getMenuData(self, md):
"""!Get menu data
@param md menu data instace
@return menu data
"""
return list(map(self._getMenuBar, md.findall('menubar')))
def GetMenu(self):
"""!Get menu
@return menu data
"""
return self._getMenuData(self.tree.getroot())
def PrintStrings(self, fh):
"""!Print menu strings to file (used for localization)
@param fh file descriptor"""
className = str(self.__class__).split('.', 1)[1]
fh.write('menustrings_%s = [\n' % className)
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:
fh.write('- %s\n' % label.replace('&', ''))
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]:
fh.write('%s - %s\n' % (' ' * level, eachItem[0]))
self._PrintTreeItems(fh, level + 1, eachItem[1])
else:
if eachItem[0]:
fh.write('%s - %s\n' % (' ' * level, eachItem[0]))
def PrintCommands(self, fh, itemSep = ' | ', menuSep = ' > '):
"""!Print commands list (command | menu item > menu item)
@param fh file descriptor
"""
level = 0
for eachMenuData in self.GetMenu():
for label, items in eachMenuData:
menuItems = [label, ]
self._PrintCommandsItems(fh, level + 1, items,
menuItems, itemSep, menuSep)
def _PrintCommandsItems(self, fh, level, menuData,
menuItems, itemSep, menuSep):
"""!Print commands item (used by PrintCommands)
@param fh file descriptor
@param menuItems list of menu items
"""
for eachItem in menuData:
if len(eachItem) == 2:
if eachItem[0]:
try:
menuItems[level] = eachItem[0]
except IndexError:
menuItems.append(eachItem[0])
self._PrintCommandsItems(fh, level + 1, eachItem[1],
menuItems, itemSep, menuSep)
else:
try:
del menuItems[level]
except IndexError:
pass
if eachItem[3]:
fh.write('%s%s' % (eachItem[3], itemSep))
fh.write(menuSep.join(map(lambda x: x.replace('&', ''), menuItems)))
fh.write('%s%s' % (menuSep, eachItem[0]))
fh.write('\n')
class ManagerData(MenuData):
def __init__(self, filename = None):
if not filename:
gisbase = os.getenv('GISBASE')
global etcwxdir
filename = os.path.join(etcwxdir, 'xml', 'menudata.xml')
MenuData.__init__(self, filename)
def GetModules(self):
"""!Create dictionary of modules used to search module by
keywords, description, etc."""
modules = dict()
for node in self.tree.getiterator():
if node.tag == 'menuitem':
module = description = ''
keywords = []
for child in node.getchildren():
if child.tag == 'help':
description = child.text
if child.tag == 'command':
module = child.text
if child.tag == 'keywords':
if child.text:
keywords = child.text.split(',')
if module:
modules[module] = { 'desc': description,
'keywords' : keywords }
if len(keywords) < 1:
print >> sys.stderr, "WARNING: Module <%s> has no keywords" % module
return modules
class ModelerData(MenuData):
def __init__(self, filename = None):
if not filename:
gisbase = os.getenv('GISBASE')
global etcwxdir
filename = os.path.join(etcwxdir, 'xml', 'menudata_modeler.xml')
MenuData.__init__(self, filename)
class PsMapData(MenuData):
def __init__(self, path = None):
"""!Menu for Cartographic Composer (psmap.py)
@path path to XML to be read (None for menudata_psmap.xml)
"""
if not path:
gisbase = os.getenv('GISBASE')
global etcwxdir
path = os.path.join(etcwxdir, 'xml', 'menudata_psmap.xml')
MenuData.__init__(self, path)
if __name__ == "__main__":
import sys
# i18N
import gettext
gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode=True)
action = 'strings'
menu = 'manager'
for arg in sys.argv:
if arg in ('strings', 'tree', 'commands', 'dump'):
action = arg
elif arg in ('manager', 'modeler'):
menu = arg
if menu == 'manager':
data = ManagerData()
else:
data = ModelerData()
if action == 'strings':
data.PrintStrings(sys.stdout)
elif action == 'tree':
data.PrintTree(sys.stdout)
elif action == 'commands':
data.PrintCommands(sys.stdout)
elif action == 'dump':
pprint.pprint(data.GetMenu(), stream = sys.stdout, indent = 2)
sys.exit(0)