menutree.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. """!
  2. @package core.menutree
  3. @brief Creates tree structure for wxGUI menus (former menudata.py)
  4. Classes:
  5. - menutree::MenuTreeModelBuilder
  6. Usage:
  7. @code
  8. python menutree.py [action] [menu]
  9. @endcode
  10. where <i>action</i>:
  11. - strings (default, used for translations)
  12. - tree (simple tree structure)
  13. - commands (command names and their place in tree)
  14. - dump (tree structure with stored data)
  15. and <i>menu</i>:
  16. - manager (Layer Manager)
  17. - modeler (Graphical Modeler)
  18. - psmap (Cartographic Composer)
  19. (C) 2013 by the GRASS Development Team
  20. This program is free software under the GNU General Public License
  21. (>=v2). Read the file COPYING that comes with GRASS for details.
  22. @author Glynn Clements (menudata.py)
  23. @author Martin Landa <landa.martin gmail.com> (menudata.py)
  24. @author Anna Petrasova <kratochanna gmail.com>
  25. """
  26. import os
  27. import sys
  28. import copy
  29. try:
  30. import xml.etree.ElementTree as etree
  31. except ImportError:
  32. import elementtree.ElementTree as etree # Python <= 2.4
  33. import wx
  34. if __name__ == '__main__':
  35. sys.path.append(os.path.join(os.environ['GISBASE'], "etc", "gui", "wxpython"))
  36. from core.treemodel import TreeModel, ModuleNode
  37. from core.settings import UserSettings
  38. if not os.getenv("GISBASE"):
  39. sys.exit("GRASS is not running. Exiting...")
  40. class MenuTreeModelBuilder:
  41. """!Abstract menu data class"""
  42. def __init__(self, filename):
  43. self.menustyle = UserSettings.Get(group = 'appearance',
  44. key = 'menustyle',
  45. subkey = 'selection')
  46. xmlTree = etree.parse(filename)
  47. self.model = TreeModel(ModuleNode)
  48. self._createModel(xmlTree)
  49. def _createModel(self, xmlTree):
  50. root = xmlTree.getroot()
  51. menubar = root.findall('menubar')[0]
  52. menus = menubar.findall('menu')
  53. for m in menus:
  54. self._createMenu(m, self.model.root)
  55. def _createMenu(self, menu, node):
  56. label = _(menu.find('label').text)
  57. items = menu.find('items')
  58. node = self.model.AppendNode(parent=node, label=label)
  59. for item in items:
  60. self._createItem(item, node)
  61. def _createItem(self, item, node):
  62. if item.tag == 'separator':
  63. data = dict(label='', description='', handler='',
  64. command='', keywords='', shortcut='', wxId='')
  65. self.model.AppendNode(parent=node, label='', data=data)
  66. elif item.tag == 'menuitem':
  67. label = _(item.find('label').text)
  68. desc = _(item.find('help').text)
  69. handler = item.find('handler').text
  70. gcmd = item.find('command') # optional
  71. keywords = item.find('keywords') # optional
  72. shortcut = item.find('shortcut') # optional
  73. wxId = item.find('id') # optional
  74. if gcmd != None:
  75. gcmd = gcmd.text
  76. else:
  77. gcmd = ""
  78. if keywords != None:
  79. keywords = keywords.text
  80. else:
  81. keywords = ""
  82. if shortcut != None:
  83. shortcut = shortcut.text
  84. else:
  85. shortcut = ""
  86. if wxId != None:
  87. wxId = eval('wx.' + wxId.text)
  88. else:
  89. wxId = wx.ID_ANY
  90. if gcmd:
  91. if self.menustyle == 1:
  92. label += ' [' + gcmd + ']'
  93. elif self.menustyle == 2:
  94. label = ' [' + gcmd + ']'
  95. data = dict(label=label, description=desc, handler=handler,
  96. command=gcmd, keywords=keywords, shortcut=shortcut, wxId=wxId)
  97. self.model.AppendNode(parent=node, label=label, data=data)
  98. elif item.tag == 'menu':
  99. self._createMenu(item, node)
  100. else:
  101. raise Exception(_("Unknow tag %s") % item.tag)
  102. def GetModel(self, separators=False):
  103. """Returns copy of model with or without separators
  104. (for menu or for search tree).
  105. """
  106. if separators:
  107. return copy.deepcopy(self.model)
  108. else:
  109. model = copy.deepcopy(self.model)
  110. removeSeparators(model)
  111. return model
  112. def PrintTree(self, fh):
  113. for child in self.model.root.children:
  114. printTree(node=child, fh=fh)
  115. def PrintStrings(self, fh):
  116. """!Print menu strings to file (used for localization)
  117. @param fh file descriptor
  118. """
  119. className = str(self.__class__).split('.', 1)[1]
  120. fh.write('menustrings_%s = [\n' % className)
  121. for child in self.model.root.children:
  122. printStrings(child, fh)
  123. fh.write(' \'\']\n')
  124. def PrintCommands(self, fh):
  125. printCommands(self.model.root, fh, itemSep=' | ', menuSep=' > ')
  126. def removeSeparators(model, node=None):
  127. if not node:
  128. node = model.root
  129. if node.label:
  130. for child in reversed(node.children):
  131. removeSeparators(model, child)
  132. else:
  133. model.RemoveNode(node)
  134. def printTree(node, fh, indent=0):
  135. if not node.label:
  136. return
  137. text = '%s- %s\n' % (' ' * indent, node.label.replace('&', ''))
  138. fh.write(text)
  139. for child in node.children:
  140. printTree(node=child, fh=fh, indent=indent + 2)
  141. def printStrings(node, fh):
  142. if node.label:
  143. fh.write(' _(%r),\n' % str(node.label))
  144. if node.data:
  145. if 'description' in node.data and node.data['description']:
  146. fh.write(' _(%r),\n' % str(node.data['description']))
  147. for child in node.children:
  148. printStrings(node=child, fh=fh)
  149. def printCommands(node, fh, itemSep, menuSep):
  150. def collectParents(node, parents):
  151. parent = node.parent
  152. if parent.parent:
  153. parents.insert(0, node.parent)
  154. collectParents(node.parent, parents)
  155. data = node.data
  156. if data and 'command' in data and data['command']:
  157. fh.write('%s%s' % (data['command'], itemSep))
  158. parents = [node]
  159. collectParents(node, parents)
  160. labels = [parent.label.replace('&', '') for parent in parents]
  161. fh.write(menuSep.join(labels))
  162. fh.write('\n')
  163. for child in node.children:
  164. printCommands(child, fh, itemSep, menuSep)
  165. if __name__ == "__main__":
  166. # i18N
  167. import gettext
  168. gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode=True)
  169. action = 'strings'
  170. menu = 'manager'
  171. for arg in sys.argv:
  172. if arg in ('strings', 'tree', 'commands', 'dump'):
  173. action = arg
  174. elif arg in ('manager', 'modeler', 'psmap'):
  175. menu = arg
  176. sys.path.append(os.path.join(os.getenv("GISBASE"), "etc", "gui", "wxpython"))
  177. if menu == 'manager':
  178. from lmgr.menudata import LayerManagerMenuData
  179. menudata = LayerManagerMenuData()
  180. elif menu == 'modeler':
  181. from gmodeler.menudata import ModelerMenuData
  182. menudata = ModelerMenuData()
  183. elif menu == 'psmap':
  184. from psmap.menudata import PsMapMenuData
  185. menudata = PsMapMenuData()
  186. if action == 'strings':
  187. menudata.PrintStrings(sys.stdout)
  188. elif action == 'tree':
  189. menudata.PrintTree(sys.stdout)
  190. elif action == 'commands':
  191. menudata.PrintCommands(sys.stdout)
  192. elif action == 'dump':
  193. print menudata.model
  194. sys.exit(0)