GRASS Programmer's Manual  6.4.4(2014)-r
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Pages
gmodeler/dialogs.py
Go to the documentation of this file.
1 """!
2 @package gmodeler.dialogs
3 
4 @brief wxGUI Graphical Modeler - dialogs
5 
6 Classes:
7  - dialogs::ModelDataDialog
8  - dialogs::ModelSearchDialog
9  - dialogs::ModelRelationDialog
10  - dialogs::ModelItemDialog
11  - dialogs::ModelLoopDialog
12  - dialogs::ModelConditionDialog
13  - dialogs::ModelListCtrl
14  - dialogs::ValiableListCtrl
15  - dialogs::ItemListCtrl
16  - dialogs::ItemCheckListCtrl
17 
18 (C) 2010-2011 by the GRASS Development Team
19 
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 
23 @author Martin Landa <landa.martin gmail.com>
24 """
25 
26 import os
27 import sys
28 
29 import wx
30 import wx.lib.mixins.listctrl as listmix
31 
32 from core import globalvar
33 from core import utils
34 from gui_core.widgets import GNotebook
35 from core.gcmd import GError, EncodeString
36 from gui_core.dialogs import ElementDialog, MapLayersDialog
37 from gui_core.ghelp import SearchModuleWindow
38 from gui_core.prompt import GPromptSTC
39 from gui_core.forms import CmdPanel
40 from gui_core.gselect import Select
41 from gmodeler.model import *
42 
43 from grass.script import task as gtask
44 
46  """!Data item properties dialog"""
47  def __init__(self, parent, shape, id = wx.ID_ANY, title = _("Data properties"),
48  style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
49  self.parent = parent
50  self.shape = shape
51 
52  label, etype = self._getLabel()
53  ElementDialog.__init__(self, parent, title, label = label, etype = etype)
54 
55  self.element = Select(parent = self.panel)
56  self.element.SetValue(shape.GetValue())
57 
58  self.Bind(wx.EVT_BUTTON, self.OnOK, self.btnOK)
59  self.Bind(wx.EVT_BUTTON, self.OnCancel, self.btnCancel)
60 
61  self.PostInit()
62 
63  if shape.GetValue():
64  self.btnOK.Enable()
65 
66  self._layout()
67  self.SetMinSize(self.GetSize())
68 
69  def _getLabel(self):
70  etype = False
71  prompt = self.shape.GetPrompt()
72  if prompt == 'raster':
73  label = _('Name of raster map:')
74  elif prompt == 'vector':
75  label = _('Name of vector map:')
76  else:
77  etype = True
78  label = _('Name of element:')
79 
80  return label, etype
81 
82  def _layout(self):
83  """!Do layout"""
84  self.dataSizer.Add(self.element, proportion=0,
85  flag=wx.EXPAND | wx.ALL, border=1)
86 
87  self.panel.SetSizer(self.sizer)
88  self.sizer.Fit(self)
89 
90  def OnOK(self, event):
91  """!Ok pressed"""
92  self.shape.SetValue(self.GetElement())
93  if self.etype:
94  elem = self.GetType()
95  if elem == 'rast':
96  self.shape.SetPrompt('raster')
97  elif elem == 'vect':
98  self.shape.SetPrompt('raster')
99 
100  self.parent.canvas.Refresh()
101  self.parent.SetStatusText('', 0)
102  self.shape.SetPropDialog(None)
103 
104  if self.IsModal():
105  event.Skip()
106  else:
107  self.Destroy()
108 
109  def OnCancel(self, event):
110  """!Cancel pressed"""
111  self.shape.SetPropDialog(None)
112  if self.IsModal():
113  event.Skip()
114  else:
115  self.Destroy()
116 
117 class ModelSearchDialog(wx.Dialog):
118  def __init__(self, parent, id = wx.ID_ANY, title = _("Add new GRASS module to the model"),
119  style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
120  """!Graphical modeler module search window
121 
122  @param parent parent window
123  @param id window id
124  @param title window title
125  @param kwargs wx.Dialogs' arguments
126  """
127  self.parent = parent
128 
129  wx.Dialog.__init__(self, parent = parent, id = id, title = title, **kwargs)
130  self.SetName("ModelerDialog")
131  self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
132 
133  self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
134 
135  self.cmdBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
136  label=" %s " % _("Command"))
137 
138  self.cmd_prompt = GPromptSTC(parent = self)
139  self.search = SearchModuleWindow(parent = self.panel, cmdPrompt = self.cmd_prompt, showTip = True)
140  wx.CallAfter(self.cmd_prompt.SetFocus)
141 
142  # get commands
143  items = self.cmd_prompt.GetCommandItems()
144 
145  self.btnCancel = wx.Button(self.panel, wx.ID_CANCEL)
146  self.btnOk = wx.Button(self.panel, wx.ID_OK)
147  self.btnOk.SetDefault()
148  self.btnOk.Enable(False)
149 
150  self.cmd_prompt.Bind(wx.EVT_KEY_UP, self.OnText)
151  self.search.searchChoice.Bind(wx.EVT_CHOICE, self.OnText)
152  self.Bind(wx.EVT_BUTTON, self.OnOk, self.btnOk)
153 
154  self._layout()
155 
156  self.SetSize((500, 275))
157 
158  def _layout(self):
159  cmdSizer = wx.StaticBoxSizer(self.cmdBox, wx.VERTICAL)
160  cmdSizer.Add(item = self.cmd_prompt, proportion = 1,
161  flag = wx.EXPAND)
162 
163  btnSizer = wx.StdDialogButtonSizer()
164  btnSizer.AddButton(self.btnCancel)
165  btnSizer.AddButton(self.btnOk)
166  btnSizer.Realize()
167 
168  mainSizer = wx.BoxSizer(wx.VERTICAL)
169  mainSizer.Add(item = self.search, proportion = 0,
170  flag = wx.EXPAND | wx.ALL, border = 3)
171  mainSizer.Add(item = cmdSizer, proportion = 1,
172  flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, border = 3)
173  mainSizer.Add(item = btnSizer, proportion = 0,
174  flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
175 
176  self.panel.SetSizer(mainSizer)
177  mainSizer.Fit(self.panel)
178 
179  self.Layout()
180 
181  def GetPanel(self):
182  """!Get dialog panel"""
183  return self.panel
184 
185  def GetCmd(self):
186  """!Get command"""
187  line = self.cmd_prompt.GetCurLine()[0].strip()
188  if len(line) == 0:
189  list()
190 
191  try:
192  cmd = utils.split(str(line))
193  except UnicodeError:
194  cmd = utils.split(utils.EncodeString((line)))
195 
196  return cmd
197 
198  def OnOk(self, event):
199  """!Button 'OK' pressed"""
200  self.btnOk.SetFocus()
201  cmd = self.GetCmd()
202 
203  if len(cmd) < 1:
204  GError(parent = self,
205  message = _("Command not defined.\n\n"
206  "Unable to add new action to the model."))
207  return
208 
209  if cmd[0] not in globalvar.grassCmd:
210  GError(parent = self,
211  message = _("'%s' is not a GRASS module.\n\n"
212  "Unable to add new action to the model.") % cmd[0])
213  return
214 
215  self.EndModal(wx.ID_OK)
216 
217  def OnText(self, event):
218  """!Text in prompt changed"""
219  if self.cmd_prompt.AutoCompActive():
220  event.Skip()
221  return
222 
223  if isinstance(event, wx.KeyEvent):
224  entry = self.cmd_prompt.GetTextLeft()
225  elif isinstance(event, wx.stc.StyledTextEvent):
226  entry = event.GetText()
227  else:
228  entry = event.GetString()
229 
230  if entry:
231  self.btnOk.Enable()
232  else:
233  self.btnOk.Enable(False)
234 
235  event.Skip()
236 
237  def Reset(self):
238  """!Reset dialog"""
239  self.search.Reset()
240  self.cmd_prompt.OnCmdErase(None)
241  self.btnOk.Enable(False)
242  self.cmd_prompt.SetFocus()
243 
244 class ModelRelationDialog(wx.Dialog):
245  """!Relation properties dialog"""
246  def __init__(self, parent, shape, id = wx.ID_ANY, title = _("Relation properties"),
247  style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
248  self.parent = parent
249  self.shape = shape
250 
251  options = self._getOptions()
252  if not options:
253  self.valid = False
254  return
255 
256  self.valid = True
257  wx.Dialog.__init__(self, parent, id, title, style = style, **kwargs)
258  self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
259 
260  self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
261 
262  self.fromBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
263  label = " %s " % _("From"))
264  self.toBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
265  label = " %s " % _("To"))
266 
267  self.option = wx.ComboBox(parent = self.panel, id = wx.ID_ANY,
268  style = wx.CB_READONLY,
269  choices = options)
270  self.option.Bind(wx.EVT_COMBOBOX, self.OnOption)
271 
272  self.btnCancel = wx.Button(self.panel, wx.ID_CANCEL)
273  self.btnOk = wx.Button(self.panel, wx.ID_OK)
274  self.btnOk.Enable(False)
275 
276  self._layout()
277 
278  def _layout(self):
279  mainSizer = wx.BoxSizer(wx.VERTICAL)
280 
281  fromSizer = wx.StaticBoxSizer(self.fromBox, wx.VERTICAL)
282  self._layoutShape(shape = self.shape.GetFrom(), sizer = fromSizer)
283  toSizer = wx.StaticBoxSizer(self.toBox, wx.VERTICAL)
284  self._layoutShape(shape = self.shape.GetTo(), sizer = toSizer)
285 
286  btnSizer = wx.StdDialogButtonSizer()
287  btnSizer.AddButton(self.btnCancel)
288  btnSizer.AddButton(self.btnOk)
289  btnSizer.Realize()
290 
291  mainSizer.Add(item = fromSizer, proportion = 0,
292  flag = wx.EXPAND | wx.ALL, border = 5)
293  mainSizer.Add(item = toSizer, proportion = 0,
294  flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
295  mainSizer.Add(item = btnSizer, proportion = 0,
296  flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
297 
298  self.panel.SetSizer(mainSizer)
299  mainSizer.Fit(self.panel)
300 
301  self.Layout()
302  self.SetSize(self.GetBestSize())
303 
304  def _layoutShape(self, shape, sizer):
305  if isinstance(shape, ModelData):
306  sizer.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
307  label = _("Data: %s") % shape.GetLog()),
308  proportion = 1, flag = wx.EXPAND | wx.ALL,
309  border = 5)
310  elif isinstance(shape, ModelAction):
311  gridSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
312  gridSizer.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
313  label = _("Command:")),
314  pos = (0, 0))
315  gridSizer.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
316  label = shape.GetName()),
317  pos = (0, 1))
318  gridSizer.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
319  label = _("Option:")),
320  flag = wx.ALIGN_CENTER_VERTICAL,
321  pos = (1, 0))
322  gridSizer.Add(item = self.option,
323  pos = (1, 1))
324  sizer.Add(item = gridSizer,
325  proportion = 1, flag = wx.EXPAND | wx.ALL,
326  border = 5)
327 
328  def _getOptions(self):
329  """!Get relevant options"""
330  items = []
331  fromShape = self.shape.GetFrom()
332  if not isinstance(fromShape, ModelData):
333  GError(parent = self.parent,
334  message = _("Relation doesn't start with data item.\n"
335  "Unable to add relation."))
336  return items
337 
338  toShape = self.shape.GetTo()
339  if not isinstance(toShape, ModelAction):
340  GError(parent = self.parent,
341  message = _("Relation doesn't point to GRASS command.\n"
342  "Unable to add relation."))
343  return items
344 
345  prompt = fromShape.GetPrompt()
346  task = toShape.GetTask()
347  for p in task.get_options()['params']:
348  if p.get('prompt', '') == prompt and \
349  'name' in p:
350  items.append(p['name'])
351 
352  if not items:
353  GError(parent = self.parent,
354  message = _("No relevant option found.\n"
355  "Unable to add relation."))
356  return items
357 
358  def GetOption(self):
359  """!Get selected option"""
360  return self.option.GetStringSelection()
361 
362  def IsValid(self):
363  """!Check if relation is valid"""
364  return self.valid
365 
366  def OnOption(self, event):
367  """!Set option"""
368  if event.GetString():
369  self.btnOk.Enable()
370  else:
371  self.btnOk.Enable(False)
372 
373 class ModelItemDialog(wx.Dialog):
374  """!Abstract item properties dialog"""
375  def __init__(self, parent, shape, title, id = wx.ID_ANY,
376  style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
377  self.parent = parent
378  self.shape = shape
379 
380  wx.Dialog.__init__(self, parent, id, title = title, style = style, **kwargs)
381 
382  self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
383 
384  self.condBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
385  label=" %s " % _("Condition"))
386  self.condText = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY,
387  value = shape.GetText())
388 
389  self.itemList = ItemCheckListCtrl(parent = self.panel,
390  window = self,
391  columns = [_("ID"), _("Name"),
392  _("Command")],
393  shape = shape)
394  self.itemList.Populate(self.parent.GetModel().GetItems())
395 
396  self.btnCancel = wx.Button(parent = self.panel, id = wx.ID_CANCEL)
397  self.btnOk = wx.Button(parent = self.panel, id = wx.ID_OK)
398  self.btnOk.SetDefault()
399 
400  def _layout(self):
401  """!Do layout (virtual method)"""
402  pass
403 
404  def GetCondition(self):
405  """!Get loop condition"""
406  return self.condText.GetValue()
407 
409  """!Loop properties dialog"""
410  def __init__(self, parent, shape, id = wx.ID_ANY, title = _("Loop properties"),
411  style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
412  ModelItemDialog.__init__(self, parent, shape, title,
413  style = style, **kwargs)
414 
415  self.listBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
416  label=" %s " % _("List of items in loop"))
417 
418  self.btnSeries = wx.Button(parent = self.panel, id = wx.ID_ANY,
419  label = _("Series"))
420  self.btnSeries.SetToolTipString(_("Define map series as condition for the loop"))
421  self.btnSeries.Bind(wx.EVT_BUTTON, self.OnSeries)
422 
423  self._layout()
424  self.SetMinSize(self.GetSize())
425  self.SetSize((500, 400))
426 
427  def _layout(self):
428  """!Do layout"""
429  sizer = wx.BoxSizer(wx.VERTICAL)
430 
431  condSizer = wx.StaticBoxSizer(self.condBox, wx.HORIZONTAL)
432  condSizer.Add(item = self.condText, proportion = 1,
433  flag = wx.ALL, border = 3)
434  condSizer.Add(item = self.btnSeries, proportion = 0,
435  flag = wx.EXPAND)
436 
437  listSizer = wx.StaticBoxSizer(self.listBox, wx.VERTICAL)
438  listSizer.Add(item = self.itemList, proportion = 1,
439  flag = wx.EXPAND | wx.ALL, border = 3)
440 
441  btnSizer = wx.StdDialogButtonSizer()
442  btnSizer.AddButton(self.btnCancel)
443  btnSizer.AddButton(self.btnOk)
444  btnSizer.Realize()
445 
446  sizer.Add(item = condSizer, proportion = 0,
447  flag = wx.EXPAND | wx.ALL, border = 3)
448  sizer.Add(item = listSizer, proportion = 1,
449  flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border = 3)
450  sizer.Add(item = btnSizer, proportion=0,
451  flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
452 
453  self.panel.SetSizer(sizer)
454  sizer.Fit(self.panel)
455 
456  self.Layout()
457 
458  def GetItems(self):
459  """!Get list of selected actions"""
460  return self.itemList.GetItems()
461 
462  def OnSeries(self, event):
463  """!Define map series as condition"""
464  dialog = MapLayersDialog(parent = self, title = _("Define series of maps"), modeler = True)
465  if dialog.ShowModal() != wx.ID_OK:
466  dialog.Destroy()
467  return
468 
469  cond = dialog.GetDSeries()
470  if not cond:
471  cond = 'map in %s' % map(lambda x: str(x), dialog.GetMapLayers())
472 
473  self.condText.SetValue(cond)
474 
475  dialog.Destroy()
476 
478  """!Condition properties dialog"""
479  def __init__(self, parent, shape, id = wx.ID_ANY, title = _("If-else properties"),
480  style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
481  ModelItemDialog.__init__(self, parent, shape, title,
482  style = style, **kwargs)
483 
484  self.listBoxIf = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
485  label=" %s " % _("List of items in 'if' block"))
486  self.itemListIf = self.itemList
487  self.itemListIf.SetName('IfBlockList')
488 
489  self.listBoxElse = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
490  label=" %s " % _("List of items in 'else' block"))
491  self.itemListElse = ItemCheckListCtrl(parent = self.panel,
492  window = self,
493  columns = [_("ID"), _("Name"),
494  _("Command")],
495  shape = shape)
496  self.itemListElse.SetName('ElseBlockList')
497  self.itemListElse.Populate(self.parent.GetModel().GetItems())
498 
499  self._layout()
500  self.SetMinSize(self.GetSize())
501  self.SetSize((500, 400))
502 
503  def _layout(self):
504  """!Do layout"""
505  sizer = wx.BoxSizer(wx.VERTICAL)
506 
507  condSizer = wx.StaticBoxSizer(self.condBox, wx.VERTICAL)
508  condSizer.Add(item = self.condText, proportion = 1,
509  flag = wx.EXPAND)
510 
511  listIfSizer = wx.StaticBoxSizer(self.listBoxIf, wx.VERTICAL)
512  listIfSizer.Add(item = self.itemListIf, proportion = 1,
513  flag = wx.EXPAND)
514  listElseSizer = wx.StaticBoxSizer(self.listBoxElse, wx.VERTICAL)
515  listElseSizer.Add(item = self.itemListElse, proportion = 1,
516  flag = wx.EXPAND)
517 
518  btnSizer = wx.StdDialogButtonSizer()
519  btnSizer.AddButton(self.btnCancel)
520  btnSizer.AddButton(self.btnOk)
521  btnSizer.Realize()
522 
523  sizer.Add(item = condSizer, proportion = 0,
524  flag = wx.EXPAND | wx.ALL, border = 3)
525  sizer.Add(item = listIfSizer, proportion = 1,
526  flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border = 3)
527  sizer.Add(item = listElseSizer, proportion = 1,
528  flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border = 3)
529  sizer.Add(item = btnSizer, proportion=0,
530  flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
531 
532  self.panel.SetSizer(sizer)
533  sizer.Fit(self.panel)
534 
535  self.Layout()
536 
537  def OnCheckItemIf(self, index, flag):
538  """!Item in if-block checked/unchecked"""
539  if flag is False:
540  return
541 
542  aId = int(self.itemListIf.GetItem(index, 0).GetText())
543  if aId in self.itemListElse.GetItems()['checked']:
544  self.itemListElse.CheckItemById(aId, False)
545 
546  def OnCheckItemElse(self, index, flag):
547  """!Item in else-block checked/unchecked"""
548  if flag is False:
549  return
550 
551  aId = int(self.itemListElse.GetItem(index, 0).GetText())
552  if aId in self.itemListIf.GetItems()['checked']:
553  self.itemListIf.CheckItemById(aId, False)
554 
555  def GetItems(self):
556  """!Get items"""
557  return { 'if' : self.itemListIf.GetItems(),
558  'else' : self.itemListElse.GetItems() }
559 
560 class ModelListCtrl(wx.ListCtrl,
561  listmix.ListCtrlAutoWidthMixin,
562  listmix.TextEditMixin,
563  listmix.ColumnSorterMixin):
564  def __init__(self, parent, columns, id = wx.ID_ANY,
565  style = wx.LC_REPORT | wx.BORDER_NONE |
566  wx.LC_SORT_ASCENDING |wx.LC_HRULES |
567  wx.LC_VRULES, **kwargs):
568  """!List of model variables"""
569  self.parent = parent
570  self.columns = columns
571  self.shape = None
572  try:
573  self.frame = parent.parent
574  except AttributeError:
575  self.frame = None
576 
577  wx.ListCtrl.__init__(self, parent, id = id, style = style, **kwargs)
578  listmix.ListCtrlAutoWidthMixin.__init__(self)
579  listmix.TextEditMixin.__init__(self)
580  listmix.ColumnSorterMixin.__init__(self, 4)
581 
582  i = 0
583  for col in columns:
584  self.InsertColumn(i, col)
585  self.SetColumnWidth(i, wx.LIST_AUTOSIZE_USEHEADER)
586  i += 1
587 
588  self.itemDataMap = {} # requested by sorter
589  self.itemCount = 0
590 
591  self.Bind(wx.EVT_LIST_BEGIN_LABEL_EDIT, self.OnBeginEdit)
592  self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnEndEdit)
593  self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick)
594  self.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.OnRightUp) #wxMSW
595  self.Bind(wx.EVT_RIGHT_UP, self.OnRightUp) #wxGTK
596 
597  def OnBeginEdit(self, event):
598  """!Editing of item started"""
599  event.Allow()
600 
601  def OnEndEdit(self, event):
602  """!Finish editing of item"""
603  pass
604 
605  def OnColClick(self, event):
606  """!Click on column header (order by)"""
607  event.Skip()
608 
610  def __init__(self, parent, columns, **kwargs):
611  """!List of model variables"""
612  ModelListCtrl.__init__(self, parent, columns, **kwargs)
613 
614  self.SetColumnWidth(2, 200) # default value
615 
616  def GetListCtrl(self):
617  """!Used by ColumnSorterMixin"""
618  return self
619 
620  def GetData(self):
621  """!Get list data"""
622  return self.itemDataMap
623 
624  def Populate(self, data):
625  """!Populate the list"""
626  self.itemDataMap = dict()
627  i = 0
628  for name, values in data.iteritems():
629  self.itemDataMap[i] = [name, values['type'],
630  values.get('value', ''),
631  values.get('description', '')]
632  i += 1
633 
634  self.itemCount = len(self.itemDataMap.keys())
635  self.DeleteAllItems()
636  i = 0
637  for name, vtype, value, desc in self.itemDataMap.itervalues():
638  index = self.InsertStringItem(sys.maxint, name)
639  self.SetStringItem(index, 0, name)
640  self.SetStringItem(index, 1, vtype)
641  self.SetStringItem(index, 2, value)
642  self.SetStringItem(index, 3, desc)
643  self.SetItemData(index, i)
644  i += 1
645 
646  def Append(self, name, vtype, value, desc):
647  """!Append new item to the list
648 
649  @return None on success
650  @return error string
651  """
652  for iname, ivtype, ivalue, idesc in self.itemDataMap.itervalues():
653  if iname == name:
654  return _("Variable <%s> already exists in the model. "
655  "Adding variable failed.") % name
656 
657  index = self.InsertStringItem(sys.maxint, name)
658  self.SetStringItem(index, 0, name)
659  self.SetStringItem(index, 1, vtype)
660  self.SetStringItem(index, 2, value)
661  self.SetStringItem(index, 3, desc)
662  self.SetItemData(index, self.itemCount)
663 
664  self.itemDataMap[self.itemCount] = [name, vtype, value, desc]
665  self.itemCount += 1
666 
667  return None
668 
669  def OnRemove(self, event):
670  """!Remove selected variable(s) from the model"""
671  item = self.GetFirstSelected()
672  while item != -1:
673  self.DeleteItem(item)
674  del self.itemDataMap[item]
675  item = self.GetFirstSelected()
676  self.parent.UpdateModelVariables()
677 
678  event.Skip()
679 
680  def OnRemoveAll(self, event):
681  """!Remove all variable(s) from the model"""
682  dlg = wx.MessageBox(parent=self,
683  message=_("Do you want to delete all variables from "
684  "the model?"),
685  caption=_("Delete variables"),
686  style=wx.YES_NO | wx.CENTRE)
687  if dlg != wx.YES:
688  return
689 
690  self.DeleteAllItems()
691  self.itemDataMap = dict()
692 
693  self.parent.UpdateModelVariables()
694 
695  def OnEndEdit(self, event):
696  """!Finish editing of item"""
697  itemIndex = event.GetIndex()
698  columnIndex = event.GetColumn()
699  nameOld = self.GetItem(itemIndex, 0).GetText()
700 
701  if columnIndex == 0: # TODO
702  event.Veto()
703 
704  self.itemDataMap[itemIndex][columnIndex] = event.GetText()
705 
706  self.parent.UpdateModelVariables()
707 
708  def OnReload(self, event):
709  """!Reload list of variables"""
710  self.Populate(self.parent.parent.GetModel().GetVariables())
711 
712  def OnRightUp(self, event):
713  """!Mouse right button up"""
714  if not hasattr(self, "popupID1"):
715  self.popupID1 = wx.NewId()
716  self.popupID2 = wx.NewId()
717  self.popupID3 = wx.NewId()
718  self.Bind(wx.EVT_MENU, self.OnRemove, id = self.popupID1)
719  self.Bind(wx.EVT_MENU, self.OnRemoveAll, id = self.popupID2)
720  self.Bind(wx.EVT_MENU, self.OnReload, id = self.popupID3)
721 
722  # generate popup-menu
723  menu = wx.Menu()
724  menu.Append(self.popupID1, _("Delete selected"))
725  menu.Append(self.popupID2, _("Delete all"))
726  if self.GetFirstSelected() == -1:
727  menu.Enable(self.popupID1, False)
728  menu.Enable(self.popupID2, False)
729 
730  menu.AppendSeparator()
731  menu.Append(self.popupID3, _("Reload"))
732 
733  self.PopupMenu(menu)
734  menu.Destroy()
735 
737  def __init__(self, parent, columns, disablePopup = False, **kwargs):
738  """!List of model actions"""
739  self.disablePopup = disablePopup
740 
741  ModelListCtrl.__init__(self, parent, columns, **kwargs)
742  self.SetColumnWidth(1, 100)
743  self.SetColumnWidth(2, 65)
744 
745  def GetListCtrl(self):
746  """!Used by ColumnSorterMixin"""
747  return self
748 
749  def GetData(self):
750  """!Get list data"""
751  return self.itemDataMap
752 
753  def Populate(self, data):
754  """!Populate the list"""
755  self.itemDataMap = dict()
756 
757  if self.shape:
758  if isinstance(self.shape, ModelCondition):
759  if self.GetName() == 'ElseBlockList':
760  shapeItems = map(lambda x: x.GetId(), self.shape.GetItems()['else'])
761  else:
762  shapeItems = map(lambda x: x.GetId(), self.shape.GetItems()['if'])
763  else:
764  shapeItems = map(lambda x: x.GetId(), self.shape.GetItems())
765  else:
766  shapeItems = list()
767 
768  i = 0
769  if len(self.columns) == 3: # ItemCheckList
770  checked = list()
771  for action in data:
772  if isinstance(action, ModelData) or \
773  action == self.shape:
774  continue
775 
776  if len(self.columns) == 3:
777  self.itemDataMap[i] = [str(action.GetId()),
778  action.GetName(),
779  action.GetLog()]
780  aId = action.GetBlockId()
781  if action.GetId() in shapeItems:
782  checked.append(aId)
783  else:
784  checked.append(None)
785  else:
786  bId = action.GetBlockId()
787  if not bId:
788  bId = ''
789  self.itemDataMap[i] = [str(action.GetId()),
790  action.GetName(),
791  ','.join(map(str, bId)),
792  action.GetLog()]
793 
794  i += 1
795 
796  self.itemCount = len(self.itemDataMap.keys())
797  self.DeleteAllItems()
798  i = 0
799  if len(self.columns) == 3:
800  for aid, name, desc in self.itemDataMap.itervalues():
801  index = self.InsertStringItem(sys.maxint, aid)
802  self.SetStringItem(index, 0, aid)
803  self.SetStringItem(index, 1, name)
804  self.SetStringItem(index, 2, desc)
805  self.SetItemData(index, i)
806  if checked[i]:
807  self.CheckItem(index, True)
808  i += 1
809  else:
810  for aid, name, inloop, desc in self.itemDataMap.itervalues():
811  index = self.InsertStringItem(sys.maxint, aid)
812  self.SetStringItem(index, 0, aid)
813  self.SetStringItem(index, 1, name)
814  self.SetStringItem(index, 2, inloop)
815  self.SetStringItem(index, 3, desc)
816  self.SetItemData(index, i)
817  i += 1
818 
819  def OnRemove(self, event):
820  """!Remove selected action(s) from the model"""
821  model = self.frame.GetModel()
822  canvas = self.frame.GetCanvas()
823 
824  item = self.GetFirstSelected()
825  while item != -1:
826  self.DeleteItem(item)
827  del self.itemDataMap[item]
828 
829  aId = self.GetItem(item, 0).GetText()
830  action = model.GetItem(int(aId))
831  if not action:
832  item = self.GetFirstSelected()
833  continue
834 
835  model.RemoveItem(action)
836  canvas.GetDiagram().RemoveShape(action)
837  self.frame.ModelChanged()
838 
839  item = self.GetFirstSelected()
840 
841  canvas.Refresh()
842 
843  event.Skip()
844 
845  def OnRemoveAll(self, event):
846  """!Remove all variable(s) from the model"""
847  deleteDialog = wx.MessageBox(parent=self,
848  message=_("Selected data records (%d) will permanently deleted "
849  "from table. Do you want to delete them?") % \
850  (len(self.listOfSQLStatements)),
851  caption=_("Delete records"),
852  style=wx.YES_NO | wx.CENTRE)
853  if deleteDialog != wx.YES:
854  return False
855 
856  self.DeleteAllItems()
857  self.itemDataMap = dict()
858 
859  self.parent.UpdateModelVariables()
860 
861  def OnEndEdit(self, event):
862  """!Finish editing of item"""
863  itemIndex = event.GetIndex()
864  columnIndex = event.GetColumn()
865 
866  self.itemDataMap[itemIndex][columnIndex] = event.GetText()
867 
868  aId = int(self.GetItem(itemIndex, 0).GetText())
869  action = self.frame.GetModel().GetItem(aId)
870  if not action:
871  event.Veto()
872  if columnIndex == 0:
873  action.SetId(int(event.GetText()))
874 
875  self.frame.ModelChanged()
876 
877  def OnReload(self, event = None):
878  """!Reload list of actions"""
879  self.Populate(self.frame.GetModel().GetItems())
880 
881  def OnRightUp(self, event):
882  """!Mouse right button up"""
883  if self.disablePopup:
884  return
885 
886  if not hasattr(self, "popupID1"):
887  self.popupID1 = wx.NewId()
888  self.popupID2 = wx.NewId()
889  self.popupID3 = wx.NewId()
890  self.popupID4 = wx.NewId()
891  self.Bind(wx.EVT_MENU, self.OnRemove, id = self.popupID1)
892  self.Bind(wx.EVT_MENU, self.OnRemoveAll, id = self.popupID2)
893  self.Bind(wx.EVT_MENU, self.OnReload, id = self.popupID3)
894  self.Bind(wx.EVT_MENU, self.OnNormalize, id = self.popupID4)
895 
896  # generate popup-menu
897  menu = wx.Menu()
898  menu.Append(self.popupID1, _("Delete selected"))
899  menu.Append(self.popupID2, _("Delete all"))
900  if self.GetFirstSelected() == -1:
901  menu.Enable(self.popupID1, False)
902  menu.Enable(self.popupID2, False)
903 
904  menu.AppendSeparator()
905  menu.Append(self.popupID4, _("Normalize"))
906  menu.Append(self.popupID3, _("Reload"))
907 
908  self.PopupMenu(menu)
909  menu.Destroy()
910 
911  def OnNormalize(self, event):
912  """!Update id of actions"""
913  model = self.frame.GetModel()
914 
915  aId = 1
916  for item in model.GetItems():
917  item.SetId(aId)
918  aId += 1
919 
920  self.OnReload(None)
921  self.frame.GetCanvas().Refresh()
922  self.frame.ModelChanged()
923 
924 class ItemCheckListCtrl(ItemListCtrl, listmix.CheckListCtrlMixin):
925  def __init__(self, parent, shape, columns, window = None, **kwargs):
926  self.parent = parent
927  self.window = window
928 
929  ItemListCtrl.__init__(self, parent, columns, disablePopup = True, **kwargs)
930  listmix.CheckListCtrlMixin.__init__(self)
931  self.SetColumnWidth(0, 50)
932 
933  self.shape = shape
934 
935  def OnBeginEdit(self, event):
936  """!Disable editing"""
937  event.Veto()
938 
939  def OnCheckItem(self, index, flag):
940  """!Item checked/unchecked"""
941  name = self.GetName()
942  if name == 'IfBlockList' and self.window:
943  self.window.OnCheckItemIf(index, flag)
944  elif name == 'ElseBlockList' and self.window:
945  self.window.OnCheckItemElse(index, flag)
946 
947  def GetItems(self):
948  """!Get list of selected actions"""
949  ids = { 'checked' : list(),
950  'unchecked' : list() }
951  for i in range(self.GetItemCount()):
952  iId = int(self.GetItem(i, 0).GetText())
953  if self.IsChecked(i):
954  ids['checked'].append(iId)
955  else:
956  ids['unchecked'].append(iId)
957 
958  return ids
959 
960  def CheckItemById(self, aId, flag):
961  """!Check/uncheck given item by id"""
962  for i in range(self.GetItemCount()):
963  iId = int(self.GetItem(i, 0).GetText())
964  if iId == aId:
965  self.CheckItem(i, flag)
966  break
def OnRightUp
Mouse right button up.
def GetData
Get list data.
def Append
Append new item to the list.
wxGUI command interface
def OnReload
Reload list of actions.
Data item properties dialog.
def OnReload
Reload list of variables.
def IsValid
Check if relation is valid.
def OnEndEdit
Finish editing of item.
def OnBeginEdit
Disable editing.
wxGUI Graphical Modeler (base classes & read/write)
def OnBeginEdit
Editing of item started.
def GetType
Get element type.
def GetItems
Get list of selected actions.
def Populate
Populate the list.
Relation properties dialog.
Core GUI widgets.
Abstract item properties dialog.
def GetListCtrl
Used by ColumnSorterMixin.
def OnRemove
Remove selected action(s) from the model.
def OnEndEdit
Finish editing of item.
def OnCheckItemIf
Item in if-block checked/unchecked.
Condition properties dialog.
wxGUI command prompt
def GetCondition
Get loop condition.
def OnColClick
Click on column header (order by)
Various dialogs used in wxGUI.
def GetListCtrl
Used by ColumnSorterMixin.
Custom control that selects elements.
def GetPanel
Get dialog panel.
def split
Platform spefic shlex.split.
Definition: core/utils.py:37
def OnRightUp
Mouse right button up.
def OnText
Text in prompt changed.
def __init__
List of model variables.
def OnOk
Button 'OK' pressed.
def __init__
Graphical modeler module search window.
def OnSeries
Define map series as condition.
def CheckItemById
Check/uncheck given item by id.
def EncodeString
Return encoded string using system locales.
Definition: core/utils.py:721
def GetElement
Return (mapName, overwrite)
def OnNormalize
Update id of actions.
def GetOption
Get selected option.
def OnRemoveAll
Remove all variable(s) from the model.
def OnRemove
Remove selected variable(s) from the model.
Help window.
def GetItems
Get list of selected actions.
def OnRemoveAll
Remove all variable(s) from the model.
def OnEndEdit
Finish editing of item.
def Populate
Populate the list.
def GetData
Get list data.
Loop properties dialog.
def OnCheckItemElse
Item in else-block checked/unchecked.
tuple range
Definition: tools.py:1406
def __init__
List of model variables.
def __init__
List of model actions.
def OnCheckItem
Item checked/unchecked.
def OnCancel
Cancel pressed.
def _getOptions
Get relevant options.
def _layout
Do layout (virtual method)