menu.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. """!
  2. @package gui_core.menu
  3. @brief Menu classes for wxGUI
  4. Classes:
  5. - menu::Menu
  6. - menu::SearchModuleWindow
  7. (C) 2010-2012 by the GRASS Development Team
  8. This program is free software under the GNU General Public License
  9. (>=v2). Read the file COPYING that comes with GRASS for details.
  10. @author Martin Landa <landa.martin gmail.com>
  11. @author Pawel Netzel (menu customization)
  12. @author Milena Nowotarska (menu customization)
  13. @author Robert Szczepanek (menu customization)
  14. @author Vaclav Petras <wenzeslaus gmail.com> (menu customization)
  15. """
  16. import wx
  17. from core import globalvar
  18. from core import utils
  19. from core.gcmd import EncodeString
  20. from gui_core.widgets import SearchModuleWidget
  21. from gui_core.treeview import CTreeView
  22. from grass.pydispatch.signal import Signal
  23. class Menu(wx.MenuBar):
  24. def __init__(self, parent, model):
  25. """!Creates menubar"""
  26. wx.MenuBar.__init__(self)
  27. self.parent = parent
  28. self.model = model
  29. self.menucmd = dict()
  30. for child in self.model.root.children:
  31. self.Append(self._createMenu(child), child.label)
  32. def _createMenu(self, node):
  33. """!Creates menu"""
  34. menu = wx.Menu()
  35. for child in node.children:
  36. if child.children:
  37. label = child.label
  38. subMenu = self._createMenu(child)
  39. menu.AppendMenu(wx.ID_ANY, label, subMenu)
  40. else:
  41. data = child.data.copy()
  42. data.pop('label')
  43. self._createMenuItem(menu, label=child.label, **data)
  44. self.parent.Bind(wx.EVT_MENU_HIGHLIGHT_ALL, self.OnMenuHighlight)
  45. return menu
  46. def _createMenuItem(self, menu, label, description, handler, command, keywords,
  47. shortcut = '', wxId = wx.ID_ANY, kind = wx.ITEM_NORMAL):
  48. """!Creates menu items
  49. There are three menu styles (menu item text styles).
  50. 1 -- label only, 2 -- label and cmd name, 3 -- cmd name only
  51. """
  52. if not label:
  53. menu.AppendSeparator()
  54. return
  55. if command:
  56. helpString = command + ' -- ' + description
  57. else:
  58. helpString = description
  59. if shortcut:
  60. label += '\t' + shortcut
  61. menuItem = menu.Append(wxId, label, helpString, kind)
  62. self.menucmd[menuItem.GetId()] = command
  63. if command:
  64. try:
  65. cmd = utils.split(str(command))
  66. except UnicodeError:
  67. cmd = utils.split(EncodeString((command)))
  68. if cmd and cmd[0] not in globalvar.grassCmd:
  69. menuItem.Enable(False)
  70. rhandler = eval('self.parent.' + handler)
  71. self.parent.Bind(wx.EVT_MENU, rhandler, menuItem)
  72. def GetData(self):
  73. """!Get menu data"""
  74. return self.model
  75. def GetCmd(self):
  76. """!Get dictionary of commands (key is id)
  77. @return dictionary of commands
  78. """
  79. return self.menucmd
  80. def OnMenuHighlight(self, event):
  81. """
  82. Default menu help handler
  83. """
  84. # Show how to get menu item info from this event handler
  85. id = event.GetMenuId()
  86. item = self.FindItemById(id)
  87. if item:
  88. text = item.GetText()
  89. help = item.GetHelp()
  90. # but in this case just call Skip so the default is done
  91. event.Skip()
  92. class SearchModuleWindow(wx.Panel):
  93. """!Menu tree and search widget for searching modules.
  94. Signal:
  95. showNotification - attribute 'message'
  96. """
  97. def __init__(self, parent, model, id = wx.ID_ANY, **kwargs):
  98. self.parent = parent # LayerManager
  99. self.showNotification = Signal('SearchModuleWindow.showNotification')
  100. wx.Panel.__init__(self, parent = parent, id = id, **kwargs)
  101. # tree
  102. self._tree = CTreeView(model=model, parent=self)
  103. self._dataBox = wx.StaticBox(parent = self, id = wx.ID_ANY,
  104. label = " %s " % _("Menu tree (double-click or Ctrl-Enter to run command)"))
  105. # search widget
  106. self._search = SearchModuleWidget(parent=self,
  107. model=model,
  108. showChoice=False)
  109. self._search.showSearchResult.connect(lambda result: self._tree.Select(result))
  110. self._search.showNotification.connect(self.showNotification)
  111. # buttons
  112. self._btnRun = wx.Button(self, id=wx.ID_OK, label=_("&Run"))
  113. self._btnRun.SetToolTipString(_("Run selected command from the menu tree"))
  114. # bindings
  115. self._btnRun.Bind(wx.EVT_BUTTON, lambda evt: self.Run())
  116. self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
  117. self._tree.selectionChanged.connect(self.OnItemSelected)
  118. self._tree.itemActivated.connect(lambda node: self.Run(node))
  119. self._layout()
  120. self._search.SetFocus()
  121. def _layout(self):
  122. """!Do dialog layout"""
  123. sizer = wx.BoxSizer(wx.VERTICAL)
  124. # body
  125. dataSizer = wx.StaticBoxSizer(self._dataBox, wx.HORIZONTAL)
  126. dataSizer.Add(item = self._tree, proportion =1,
  127. flag = wx.EXPAND)
  128. # buttons
  129. btnSizer = wx.BoxSizer(wx.HORIZONTAL)
  130. btnSizer.Add(item = self._btnRun, proportion = 0)
  131. sizer.Add(item = dataSizer, proportion = 1,
  132. flag = wx.EXPAND | wx.ALL, border = 5)
  133. sizer.Add(item = self._search, proportion = 0,
  134. flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
  135. sizer.Add(item = btnSizer, proportion = 0,
  136. flag = wx.ALIGN_RIGHT | wx.BOTTOM | wx.RIGHT, border = 5)
  137. sizer.Fit(self)
  138. sizer.SetSizeHints(self)
  139. self.SetSizer(sizer)
  140. self.Fit()
  141. self.SetAutoLayout(True)
  142. self.Layout()
  143. def Run(self, module=None):
  144. """!Run selected command.
  145. @param module module (represented by tree node)
  146. """
  147. if module is None:
  148. if not self._tree.GetSelected():
  149. return
  150. module = self._tree.GetSelected()[0]
  151. data = module.data
  152. if not data:
  153. return
  154. handler = 'self.parent.' + data['handler'].lstrip('self.')
  155. if data['command']:
  156. eval(handler)(event=None, cmd=data['command'].split())
  157. else:
  158. eval(handler)(event=None)
  159. def OnKeyUp(self, event):
  160. """!Key or key combination pressed"""
  161. if event.ControlDown() and event.GetKeyCode() == wx.WXK_RETURN:
  162. self.Run()
  163. def OnItemSelected(self, node):
  164. """!Item selected"""
  165. data = node.data
  166. if not data or 'command' not in data:
  167. return
  168. if data['command']:
  169. label = data['command'] + ' -- ' + data['description']
  170. else:
  171. label = data['description']
  172. self.showNotification.emit(message=label)