GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
menu.py
Go to the documentation of this file.
1 """!
2 @package gui_core.menu
3 
4 @brief Menu classes for wxGUI
5 
6 Classes:
7  - menu::Menu
8  - menu::MenuTreeWindow
9  - menu::MenuTree
10 
11 (C) 2010-2012 by the GRASS Development Team
12 
13 This program is free software under the GNU General Public License
14 (>=v2). Read the file COPYING that comes with GRASS for details.
15 
16 @author Martin Landa <landa.martin gmail.com>
17 @author Pawel Netzel (menu customization)
18 @author Milena Nowotarska (menu customization)
19 @author Robert Szczepanek (menu customization)
20 @author Vaclav Petras <wenzeslaus gmail.com> (menu customization)
21 """
22 
23 import wx
24 
25 from core import globalvar
26 from core import utils
27 from core.gcmd import EncodeString
28 from core.settings import UserSettings
29 from gui_core.widgets import ItemTree
30 from lmgr.menudata import ManagerData
31 from gui_core.ghelp import SearchModuleWindow
32 
33 class Menu(wx.MenuBar):
34  def __init__(self, parent, data):
35  """!Creates menubar"""
36  wx.MenuBar.__init__(self)
37  self.parent = parent
38  self.menudata = data
39  self.menucmd = dict()
40 
41  self.menustyle = UserSettings.Get(group = 'appearance', key = 'menustyle', subkey = 'selection')
42 
43  for eachMenuData in self.menudata.GetMenu():
44  for eachHeading in eachMenuData:
45  menuLabel = eachHeading[0]
46  menuItems = eachHeading[1]
47  self.Append(self._createMenu(menuItems), menuLabel)
48 
49  def _createMenu(self, menuData):
50  """!Creates menu"""
51  menu = wx.Menu()
52  for eachItem in menuData:
53  if len(eachItem) == 2:
54  label = eachItem[0]
55  subMenu = self._createMenu(eachItem[1])
56  menu.AppendMenu(wx.ID_ANY, label, subMenu)
57  else:
58  self._createMenuItem(menu, self.menustyle, *eachItem)
59 
60  self.parent.Bind(wx.EVT_MENU_HIGHLIGHT_ALL, self.OnMenuHighlight)
61 
62  return menu
63 
64  def _createMenuItem(self, menu, menustyle, label, help, handler, gcmd, keywords,
65  shortcut = '', wxId = wx.ID_ANY, kind = wx.ITEM_NORMAL):
66  """!Creates menu items
67  There are three menu styles (menu item text styles).
68  1 -- label only, 2 -- label and cmd name, 3 -- cmd name only
69  """
70  if not label:
71  menu.AppendSeparator()
72  return
73 
74  if len(gcmd) > 0:
75  helpString = gcmd + ' -- ' + help
76  if menustyle == 1:
77  label += ' [' + gcmd + ']'
78  elif menustyle == 2:
79  label = ' [' + gcmd + ']'
80  else:
81  helpString = help
82 
83  if shortcut:
84  label += '\t' + shortcut
85 
86  menuItem = menu.Append(wxId, label, helpString, kind)
87 
88  self.menucmd[menuItem.GetId()] = gcmd
89 
90  if gcmd:
91  try:
92  cmd = utils.split(str(gcmd))
93  except UnicodeError:
94  cmd = utils.split(EncodeString((gcmd)))
95  if cmd and cmd[0] not in globalvar.grassCmd:
96  menuItem.Enable(False)
97 
98  rhandler = eval('self.parent.' + handler)
99 
100  self.parent.Bind(wx.EVT_MENU, rhandler, menuItem)
101 
102  def GetData(self):
103  """!Get menu data"""
104  return self.menudata
105 
106  def GetCmd(self):
107  """!Get list of commands
108 
109  @return list of commands
110  """
111  return self.menucmd
112 
113  def OnMenuHighlight(self, event):
114  """
115  Default menu help handler
116  """
117  # Show how to get menu item info from this event handler
118  id = event.GetMenuId()
119  item = self.FindItemById(id)
120  if item:
121  text = item.GetText()
122  help = item.GetHelp()
123 
124  # but in this case just call Skip so the default is done
125  event.Skip()
126 
127 class MenuTreeWindow(wx.Panel):
128  """!Show menu tree"""
129  def __init__(self, parent, id = wx.ID_ANY, **kwargs):
130  self.parent = parent # LayerManager
131 
132  wx.Panel.__init__(self, parent = parent, id = id, **kwargs)
133 
134  self.dataBox = wx.StaticBox(parent = self, id = wx.ID_ANY,
135  label = " %s " % _("Menu tree (double-click or Ctrl-Enter to run command)"))
136  # tree
137  self.tree = MenuTree(parent = self, data = ManagerData())
138  self.tree.Load()
139 
140  # search widget
141  self.search = SearchModuleWindow(parent = self, showChoice = False)
142 
143  # buttons
144  self.btnRun = wx.Button(self, id = wx.ID_OK, label = _("&Run"))
145  self.btnRun.SetToolTipString(_("Run selected command from the menu tree"))
146  self.btnRun.Enable(False)
147 
148  # bindings
149  self.btnRun.Bind(wx.EVT_BUTTON, self.OnRun)
150  self.tree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnItemActivated)
151  self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnItemSelected)
152  self.search.GetCtrl().Bind(wx.EVT_TEXT, self.OnUpdateStatusBar)
153  self.search.GetCtrl().Bind(wx.EVT_KEY_UP, self.OnKeyUp)
154 
155  self._layout()
156 
157  self.search.SetFocus()
158 
159  def _layout(self):
160  """!Do dialog layout"""
161  sizer = wx.BoxSizer(wx.VERTICAL)
162 
163  # body
164  dataSizer = wx.StaticBoxSizer(self.dataBox, wx.HORIZONTAL)
165  dataSizer.Add(item = self.tree, proportion =1,
166  flag = wx.EXPAND)
167 
168  # buttons
169  btnSizer = wx.BoxSizer(wx.HORIZONTAL)
170  btnSizer.Add(item = self.btnRun, proportion = 0)
171 
172  sizer.Add(item = dataSizer, proportion = 1,
173  flag = wx.EXPAND | wx.ALL, border = 5)
174 
175  sizer.Add(item = self.search, proportion = 0,
176  flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
177 
178  sizer.Add(item = btnSizer, proportion = 0,
179  flag = wx.ALIGN_RIGHT | wx.BOTTOM | wx.RIGHT, border = 5)
180 
181  sizer.Fit(self)
182  sizer.SetSizeHints(self)
183 
184  self.SetSizer(sizer)
185 
186  self.Fit()
187  self.SetAutoLayout(True)
188  self.Layout()
189 
190  def OnCloseWindow(self, event):
191  """!Close window"""
192  self.Destroy()
193 
194  def OnRun(self, event):
195  """!Run selected command"""
196  if not self.tree.GetSelected():
197  return # should not happen
198 
199  data = self.tree.GetPyData(self.tree.GetSelected())
200  if not data:
201  return
202 
203  handler = 'self.parent.' + data['handler'].lstrip('self.')
204  if data['handler'] == 'self.OnXTerm':
205  wx.MessageBox(parent = self,
206  message = _('You must run this command from the menu or command line',
207  'This command require an XTerm'),
208  caption = _('Message'), style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
209  elif data['command']:
210  eval(handler)(event = None, cmd = data['command'].split())
211  else:
212  eval(handler)(None)
213 
214  def OnKeyUp(self, event):
215  if event.GetKeyCode() == wx.WXK_RETURN:
216  if event.ControlDown():
217  self.OnRun(event)
218  else:
219  self.OnShowItem(event)
220 
221  def OnShowItem(self, event):
222  """!Show selected item"""
223  self.tree.OnShowItem(event)
224  if self.tree.GetSelected():
225  self.btnRun.Enable()
226  else:
227  self.btnRun.Enable(False)
228 
229  def OnItemActivated(self, event):
230  """!Item activated (double-click)"""
231  item = event.GetItem()
232  if not item or not item.IsOk():
233  return
234 
235  data = self.tree.GetPyData(item)
236  if not data or 'command' not in data:
237  return
238 
239  self.tree.itemSelected = item
240 
241  self.OnRun(None)
242 
243  def OnItemSelected(self, event):
244  """!Item selected"""
245  item = event.GetItem()
246  if not item or not item.IsOk():
247  return
248 
249  data = self.tree.GetPyData(item)
250  if not data or 'command' not in data:
251  return
252 
253  if data['command']:
254  label = data['command'] + ' -- ' + data['description']
255  else:
256  label = data['description']
257 
258  self.parent.SetStatusText(label, 0)
259 
260  def OnUpdateStatusBar(self, event):
261  """!Update statusbar text"""
262  element = self.search.GetSelection()
263  value = event.GetEventObject().GetValue()
264  self.tree.SearchItems(element = element, value = value)
265 
266  nItems = len(self.tree.itemsMarked)
267  if value:
268  self.parent.SetStatusText(_("%d modules match") % nItems, 0)
269  else:
270  self.parent.SetStatusText("", 0)
271 
272  event.Skip()
273 
274 class MenuTree(ItemTree):
275  """!Menu tree class"""
276  def __init__(self, parent, data, **kwargs):
277  self.parent = parent
278  self.menudata = data
279 
280  super(MenuTree, self).__init__(parent, **kwargs)
281 
282  self.menustyle = UserSettings.Get(group = 'appearance', key = 'menustyle', subkey = 'selection')
283 
284  def Load(self, data = None):
285  """!Load menu data tree
286 
287  @param data menu data (None to use self.menudata)
288  """
289  if not data:
290  data = self.menudata
291 
292  self.itemsMarked = [] # list of marked items
293  for eachMenuData in data.GetMenu():
294  for label, items in eachMenuData:
295  item = self.AppendItem(parentId = self.root,
296  text = label.replace('&', ''))
297  self.__AppendItems(item, items)
298 
299  def __AppendItems(self, item, data):
300  """!Append items into tree (used by Load()
301 
302  @param item tree item (parent)
303  @parent data menu data"""
304  for eachItem in data:
305  if len(eachItem) == 2:
306  if eachItem[0]:
307  itemSub = self.AppendItem(parentId = item,
308  text = eachItem[0])
309  self.__AppendItems(itemSub, eachItem[1])
310  else:
311  if eachItem[0]:
312  label = eachItem[0]
313  if eachItem[3]:
314  if self.menustyle == 1:
315  label += ' [' + eachItem[3] + ']'
316  elif self.menustyle == 2:
317  label = '[' + eachItem[3] + ']'
318 
319  itemNew = self.AppendItem(parentId = item,
320  text = label)
321 
322  data = { 'item' : eachItem[0],
323  'description' : eachItem[1],
324  'handler' : eachItem[2],
325  'command' : eachItem[3],
326  'keywords' : eachItem[4] }
327 
328  self.SetPyData(itemNew, data)
def __init__
Creates menubar.
Definition: menu.py:34
def EncodeString
Return encoded string using system locales.
Definition: gcmd.py:85
def GetValue
Definition: widgets.py:118
menucmd
Definition: menu.py:39
wxGUI command interface
def __AppendItems
Append items into tree (used by Load()
Definition: menu.py:299
Menu tree class.
Definition: menu.py:274
Core GUI widgets.
def OnMenuHighlight
Definition: menu.py:113
def OnItemSelected
Item selected.
Definition: menu.py:243
def _layout
Do dialog layout.
Definition: menu.py:159
def split
Platform spefic shlex.split.
Definition: core/utils.py:37
parent
Definition: menu.py:37
def GetData
Get menu data.
Definition: menu.py:102
def OnItemActivated
Item activated (double-click)
Definition: menu.py:229
menustyle
Definition: menu.py:41
menudata
Definition: menu.py:38
def _createMenu
Creates menu.
Definition: menu.py:49
def Load
Load menu data tree.
Definition: menu.py:284
def __init__
Definition: menu.py:276
Help window.
def OnCloseWindow
Close window.
Definition: menu.py:190
def _createMenuItem
Creates menu items There are three menu styles (menu item text styles).
Definition: menu.py:65
Show menu tree.
Definition: menu.py:127
def OnShowItem
Show selected item.
Definition: menu.py:221
def OnRun
Run selected command.
Definition: menu.py:194
Default GUI settings.
def GetCmd
Get list of commands.
Definition: menu.py:106
def OnUpdateStatusBar
Update statusbar text.
Definition: menu.py:260