|
GRASS Programmer's Manual
6.5.svn(2012)-r51648
|
00001 """! 00002 @package gmodeler.dialogs 00003 00004 @brief wxGUI Graphical Modeler - dialogs 00005 00006 Classes: 00007 - dialogs::ModelDataDialog 00008 - dialogs::ModelSearchDialog 00009 - dialogs::ModelRelationDialog 00010 - dialogs::ModelItemDialog 00011 - dialogs::ModelLoopDialog 00012 - dialogs::ModelConditionDialog 00013 - dialogs::ModelListCtrl 00014 - dialogs::ValiableListCtrl 00015 - dialogs::ItemListCtrl 00016 - dialogs::ItemCheckListCtrl 00017 00018 (C) 2010-2011 by the GRASS Development Team 00019 00020 This program is free software under the GNU General Public License 00021 (>=v2). Read the file COPYING that comes with GRASS for details. 00022 00023 @author Martin Landa <landa.martin gmail.com> 00024 """ 00025 00026 import os 00027 import sys 00028 00029 import wx 00030 import wx.lib.mixins.listctrl as listmix 00031 00032 from core import globalvar 00033 from core import utils 00034 from gui_core.widgets import GNotebook 00035 from core.gcmd import GError, EncodeString 00036 from gui_core.dialogs import ElementDialog, MapLayersDialog 00037 from gui_core.ghelp import SearchModuleWindow 00038 from gui_core.prompt import GPromptSTC 00039 from gui_core.forms import CmdPanel 00040 from gui_core.gselect import Select 00041 from gmodeler.model import * 00042 00043 from grass.script import task as gtask 00044 00045 class ModelDataDialog(ElementDialog): 00046 """!Data item properties dialog""" 00047 def __init__(self, parent, shape, id = wx.ID_ANY, title = _("Data properties"), 00048 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER): 00049 self.parent = parent 00050 self.shape = shape 00051 00052 label, etype = self._getLabel() 00053 ElementDialog.__init__(self, parent, title, label = label, etype = etype) 00054 00055 self.element = Select(parent = self.panel) 00056 self.element.SetValue(shape.GetValue()) 00057 00058 self.Bind(wx.EVT_BUTTON, self.OnOK, self.btnOK) 00059 self.Bind(wx.EVT_BUTTON, self.OnCancel, self.btnCancel) 00060 00061 self.PostInit() 00062 00063 if shape.GetValue(): 00064 self.btnOK.Enable() 00065 00066 self._layout() 00067 self.SetMinSize(self.GetSize()) 00068 00069 def _getLabel(self): 00070 etype = False 00071 prompt = self.shape.GetPrompt() 00072 if prompt == 'raster': 00073 label = _('Name of raster map:') 00074 elif prompt == 'vector': 00075 label = _('Name of vector map:') 00076 else: 00077 etype = True 00078 label = _('Name of element:') 00079 00080 return label, etype 00081 00082 def _layout(self): 00083 """!Do layout""" 00084 self.dataSizer.Add(self.element, proportion=0, 00085 flag=wx.EXPAND | wx.ALL, border=1) 00086 00087 self.panel.SetSizer(self.sizer) 00088 self.sizer.Fit(self) 00089 00090 def OnOK(self, event): 00091 """!Ok pressed""" 00092 self.shape.SetValue(self.GetElement()) 00093 if self.etype: 00094 elem = self.GetType() 00095 if elem == 'rast': 00096 self.shape.SetPrompt('raster') 00097 elif elem == 'vect': 00098 self.shape.SetPrompt('raster') 00099 00100 self.parent.canvas.Refresh() 00101 self.parent.SetStatusText('', 0) 00102 self.shape.SetPropDialog(None) 00103 00104 if self.IsModal(): 00105 event.Skip() 00106 else: 00107 self.Destroy() 00108 00109 def OnCancel(self, event): 00110 """!Cancel pressed""" 00111 self.shape.SetPropDialog(None) 00112 if self.IsModal(): 00113 event.Skip() 00114 else: 00115 self.Destroy() 00116 00117 class ModelSearchDialog(wx.Dialog): 00118 def __init__(self, parent, id = wx.ID_ANY, title = _("Add new GRASS module to the model"), 00119 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs): 00120 """!Graphical modeler module search window 00121 00122 @param parent parent window 00123 @param id window id 00124 @param title window title 00125 @param kwargs wx.Dialogs' arguments 00126 """ 00127 self.parent = parent 00128 00129 wx.Dialog.__init__(self, parent = parent, id = id, title = title, **kwargs) 00130 self.SetName("ModelerDialog") 00131 self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO)) 00132 00133 self.panel = wx.Panel(parent = self, id = wx.ID_ANY) 00134 00135 self.cmdBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY, 00136 label=" %s " % _("Command")) 00137 00138 self.cmd_prompt = GPromptSTC(parent = self) 00139 self.search = SearchModuleWindow(parent = self.panel, cmdPrompt = self.cmd_prompt, showTip = True) 00140 wx.CallAfter(self.cmd_prompt.SetFocus) 00141 00142 # get commands 00143 items = self.cmd_prompt.GetCommandItems() 00144 00145 self.btnCancel = wx.Button(self.panel, wx.ID_CANCEL) 00146 self.btnOk = wx.Button(self.panel, wx.ID_OK) 00147 self.btnOk.SetDefault() 00148 self.btnOk.Enable(False) 00149 00150 self.cmd_prompt.Bind(wx.EVT_KEY_UP, self.OnText) 00151 self.search.searchChoice.Bind(wx.EVT_CHOICE, self.OnText) 00152 self.Bind(wx.EVT_BUTTON, self.OnOk, self.btnOk) 00153 00154 self._layout() 00155 00156 self.SetSize((500, 275)) 00157 00158 def _layout(self): 00159 cmdSizer = wx.StaticBoxSizer(self.cmdBox, wx.VERTICAL) 00160 cmdSizer.Add(item = self.cmd_prompt, proportion = 1, 00161 flag = wx.EXPAND) 00162 00163 btnSizer = wx.StdDialogButtonSizer() 00164 btnSizer.AddButton(self.btnCancel) 00165 btnSizer.AddButton(self.btnOk) 00166 btnSizer.Realize() 00167 00168 mainSizer = wx.BoxSizer(wx.VERTICAL) 00169 mainSizer.Add(item = self.search, proportion = 0, 00170 flag = wx.EXPAND | wx.ALL, border = 3) 00171 mainSizer.Add(item = cmdSizer, proportion = 1, 00172 flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, border = 3) 00173 mainSizer.Add(item = btnSizer, proportion = 0, 00174 flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5) 00175 00176 self.panel.SetSizer(mainSizer) 00177 mainSizer.Fit(self.panel) 00178 00179 self.Layout() 00180 00181 def GetPanel(self): 00182 """!Get dialog panel""" 00183 return self.panel 00184 00185 def GetCmd(self): 00186 """!Get command""" 00187 line = self.cmd_prompt.GetCurLine()[0].strip() 00188 if len(line) == 0: 00189 list() 00190 00191 try: 00192 cmd = utils.split(str(line)) 00193 except UnicodeError: 00194 cmd = utils.split(utils.EncodeString((line))) 00195 00196 return cmd 00197 00198 def OnOk(self, event): 00199 """!Button 'OK' pressed""" 00200 self.btnOk.SetFocus() 00201 cmd = self.GetCmd() 00202 00203 if len(cmd) < 1: 00204 GError(parent = self, 00205 message = _("Command not defined.\n\n" 00206 "Unable to add new action to the model.")) 00207 return 00208 00209 if cmd[0] not in globalvar.grassCmd: 00210 GError(parent = self, 00211 message = _("'%s' is not a GRASS module.\n\n" 00212 "Unable to add new action to the model.") % cmd[0]) 00213 return 00214 00215 self.EndModal(wx.ID_OK) 00216 00217 def OnText(self, event): 00218 """!Text in prompt changed""" 00219 if self.cmd_prompt.AutoCompActive(): 00220 event.Skip() 00221 return 00222 00223 if isinstance(event, wx.KeyEvent): 00224 entry = self.cmd_prompt.GetTextLeft() 00225 elif isinstance(event, wx.stc.StyledTextEvent): 00226 entry = event.GetText() 00227 else: 00228 entry = event.GetString() 00229 00230 if entry: 00231 self.btnOk.Enable() 00232 else: 00233 self.btnOk.Enable(False) 00234 00235 event.Skip() 00236 00237 def Reset(self): 00238 """!Reset dialog""" 00239 self.search.Reset() 00240 self.cmd_prompt.OnCmdErase(None) 00241 self.btnOk.Enable(False) 00242 self.cmd_prompt.SetFocus() 00243 00244 class ModelRelationDialog(wx.Dialog): 00245 """!Relation properties dialog""" 00246 def __init__(self, parent, shape, id = wx.ID_ANY, title = _("Relation properties"), 00247 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs): 00248 self.parent = parent 00249 self.shape = shape 00250 00251 options = self._getOptions() 00252 if not options: 00253 self.valid = False 00254 return 00255 00256 self.valid = True 00257 wx.Dialog.__init__(self, parent, id, title, style = style, **kwargs) 00258 self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO)) 00259 00260 self.panel = wx.Panel(parent = self, id = wx.ID_ANY) 00261 00262 self.fromBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY, 00263 label = " %s " % _("From")) 00264 self.toBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY, 00265 label = " %s " % _("To")) 00266 00267 self.option = wx.ComboBox(parent = self.panel, id = wx.ID_ANY, 00268 style = wx.CB_READONLY, 00269 choices = options) 00270 self.option.Bind(wx.EVT_COMBOBOX, self.OnOption) 00271 00272 self.btnCancel = wx.Button(self.panel, wx.ID_CANCEL) 00273 self.btnOk = wx.Button(self.panel, wx.ID_OK) 00274 self.btnOk.Enable(False) 00275 00276 self._layout() 00277 00278 def _layout(self): 00279 mainSizer = wx.BoxSizer(wx.VERTICAL) 00280 00281 fromSizer = wx.StaticBoxSizer(self.fromBox, wx.VERTICAL) 00282 self._layoutShape(shape = self.shape.GetFrom(), sizer = fromSizer) 00283 toSizer = wx.StaticBoxSizer(self.toBox, wx.VERTICAL) 00284 self._layoutShape(shape = self.shape.GetTo(), sizer = toSizer) 00285 00286 btnSizer = wx.StdDialogButtonSizer() 00287 btnSizer.AddButton(self.btnCancel) 00288 btnSizer.AddButton(self.btnOk) 00289 btnSizer.Realize() 00290 00291 mainSizer.Add(item = fromSizer, proportion = 0, 00292 flag = wx.EXPAND | wx.ALL, border = 5) 00293 mainSizer.Add(item = toSizer, proportion = 0, 00294 flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5) 00295 mainSizer.Add(item = btnSizer, proportion = 0, 00296 flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5) 00297 00298 self.panel.SetSizer(mainSizer) 00299 mainSizer.Fit(self.panel) 00300 00301 self.Layout() 00302 self.SetSize(self.GetBestSize()) 00303 00304 def _layoutShape(self, shape, sizer): 00305 if isinstance(shape, ModelData): 00306 sizer.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY, 00307 label = _("Data: %s") % shape.GetLog()), 00308 proportion = 1, flag = wx.EXPAND | wx.ALL, 00309 border = 5) 00310 elif isinstance(shape, ModelAction): 00311 gridSizer = wx.GridBagSizer (hgap = 5, vgap = 5) 00312 gridSizer.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY, 00313 label = _("Command:")), 00314 pos = (0, 0)) 00315 gridSizer.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY, 00316 label = shape.GetName()), 00317 pos = (0, 1)) 00318 gridSizer.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY, 00319 label = _("Option:")), 00320 flag = wx.ALIGN_CENTER_VERTICAL, 00321 pos = (1, 0)) 00322 gridSizer.Add(item = self.option, 00323 pos = (1, 1)) 00324 sizer.Add(item = gridSizer, 00325 proportion = 1, flag = wx.EXPAND | wx.ALL, 00326 border = 5) 00327 00328 def _getOptions(self): 00329 """!Get relevant options""" 00330 items = [] 00331 fromShape = self.shape.GetFrom() 00332 if not isinstance(fromShape, ModelData): 00333 GError(parent = self.parent, 00334 message = _("Relation doesn't start with data item.\n" 00335 "Unable to add relation.")) 00336 return items 00337 00338 toShape = self.shape.GetTo() 00339 if not isinstance(toShape, ModelAction): 00340 GError(parent = self.parent, 00341 message = _("Relation doesn't point to GRASS command.\n" 00342 "Unable to add relation.")) 00343 return items 00344 00345 prompt = fromShape.GetPrompt() 00346 task = toShape.GetTask() 00347 for p in task.get_options()['params']: 00348 if p.get('prompt', '') == prompt and \ 00349 'name' in p: 00350 items.append(p['name']) 00351 00352 if not items: 00353 GError(parent = self.parent, 00354 message = _("No relevant option found.\n" 00355 "Unable to add relation.")) 00356 return items 00357 00358 def GetOption(self): 00359 """!Get selected option""" 00360 return self.option.GetStringSelection() 00361 00362 def IsValid(self): 00363 """!Check if relation is valid""" 00364 return self.valid 00365 00366 def OnOption(self, event): 00367 """!Set option""" 00368 if event.GetString(): 00369 self.btnOk.Enable() 00370 else: 00371 self.btnOk.Enable(False) 00372 00373 class ModelItemDialog(wx.Dialog): 00374 """!Abstract item properties dialog""" 00375 def __init__(self, parent, shape, title, id = wx.ID_ANY, 00376 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs): 00377 self.parent = parent 00378 self.shape = shape 00379 00380 wx.Dialog.__init__(self, parent, id, title = title, style = style, **kwargs) 00381 00382 self.panel = wx.Panel(parent = self, id = wx.ID_ANY) 00383 00384 self.condBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY, 00385 label=" %s " % _("Condition")) 00386 self.condText = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY, 00387 value = shape.GetText()) 00388 00389 self.itemList = ItemCheckListCtrl(parent = self.panel, 00390 window = self, 00391 columns = [_("ID"), _("Name"), 00392 _("Command")], 00393 shape = shape) 00394 self.itemList.Populate(self.parent.GetModel().GetItems()) 00395 00396 self.btnCancel = wx.Button(parent = self.panel, id = wx.ID_CANCEL) 00397 self.btnOk = wx.Button(parent = self.panel, id = wx.ID_OK) 00398 self.btnOk.SetDefault() 00399 00400 def _layout(self): 00401 """!Do layout (virtual method)""" 00402 pass 00403 00404 def GetCondition(self): 00405 """!Get loop condition""" 00406 return self.condText.GetValue() 00407 00408 class ModelLoopDialog(ModelItemDialog): 00409 """!Loop properties dialog""" 00410 def __init__(self, parent, shape, id = wx.ID_ANY, title = _("Loop properties"), 00411 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs): 00412 ModelItemDialog.__init__(self, parent, shape, title, 00413 style = style, **kwargs) 00414 00415 self.listBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY, 00416 label=" %s " % _("List of items in loop")) 00417 00418 self.btnSeries = wx.Button(parent = self.panel, id = wx.ID_ANY, 00419 label = _("Series")) 00420 self.btnSeries.SetToolTipString(_("Define map series as condition for the loop")) 00421 self.btnSeries.Bind(wx.EVT_BUTTON, self.OnSeries) 00422 00423 self._layout() 00424 self.SetMinSize(self.GetSize()) 00425 self.SetSize((500, 400)) 00426 00427 def _layout(self): 00428 """!Do layout""" 00429 sizer = wx.BoxSizer(wx.VERTICAL) 00430 00431 condSizer = wx.StaticBoxSizer(self.condBox, wx.HORIZONTAL) 00432 condSizer.Add(item = self.condText, proportion = 1, 00433 flag = wx.ALL, border = 3) 00434 condSizer.Add(item = self.btnSeries, proportion = 0, 00435 flag = wx.EXPAND) 00436 00437 listSizer = wx.StaticBoxSizer(self.listBox, wx.VERTICAL) 00438 listSizer.Add(item = self.itemList, proportion = 1, 00439 flag = wx.EXPAND | wx.ALL, border = 3) 00440 00441 btnSizer = wx.StdDialogButtonSizer() 00442 btnSizer.AddButton(self.btnCancel) 00443 btnSizer.AddButton(self.btnOk) 00444 btnSizer.Realize() 00445 00446 sizer.Add(item = condSizer, proportion = 0, 00447 flag = wx.EXPAND | wx.ALL, border = 3) 00448 sizer.Add(item = listSizer, proportion = 1, 00449 flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border = 3) 00450 sizer.Add(item = btnSizer, proportion=0, 00451 flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5) 00452 00453 self.panel.SetSizer(sizer) 00454 sizer.Fit(self.panel) 00455 00456 self.Layout() 00457 00458 def GetItems(self): 00459 """!Get list of selected actions""" 00460 return self.itemList.GetItems() 00461 00462 def OnSeries(self, event): 00463 """!Define map series as condition""" 00464 dialog = MapLayersDialog(parent = self, title = _("Define series of maps"), modeler = True) 00465 if dialog.ShowModal() != wx.ID_OK: 00466 dialog.Destroy() 00467 return 00468 00469 cond = dialog.GetDSeries() 00470 if not cond: 00471 cond = 'map in %s' % map(lambda x: str(x), dialog.GetMapLayers()) 00472 00473 self.condText.SetValue(cond) 00474 00475 dialog.Destroy() 00476 00477 class ModelConditionDialog(ModelItemDialog): 00478 """!Condition properties dialog""" 00479 def __init__(self, parent, shape, id = wx.ID_ANY, title = _("If-else properties"), 00480 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs): 00481 ModelItemDialog.__init__(self, parent, shape, title, 00482 style = style, **kwargs) 00483 00484 self.listBoxIf = wx.StaticBox(parent = self.panel, id = wx.ID_ANY, 00485 label=" %s " % _("List of items in 'if' block")) 00486 self.itemListIf = self.itemList 00487 self.itemListIf.SetName('IfBlockList') 00488 00489 self.listBoxElse = wx.StaticBox(parent = self.panel, id = wx.ID_ANY, 00490 label=" %s " % _("List of items in 'else' block")) 00491 self.itemListElse = ItemCheckListCtrl(parent = self.panel, 00492 window = self, 00493 columns = [_("ID"), _("Name"), 00494 _("Command")], 00495 shape = shape) 00496 self.itemListElse.SetName('ElseBlockList') 00497 self.itemListElse.Populate(self.parent.GetModel().GetItems()) 00498 00499 self._layout() 00500 self.SetMinSize(self.GetSize()) 00501 self.SetSize((500, 400)) 00502 00503 def _layout(self): 00504 """!Do layout""" 00505 sizer = wx.BoxSizer(wx.VERTICAL) 00506 00507 condSizer = wx.StaticBoxSizer(self.condBox, wx.VERTICAL) 00508 condSizer.Add(item = self.condText, proportion = 1, 00509 flag = wx.EXPAND) 00510 00511 listIfSizer = wx.StaticBoxSizer(self.listBoxIf, wx.VERTICAL) 00512 listIfSizer.Add(item = self.itemListIf, proportion = 1, 00513 flag = wx.EXPAND) 00514 listElseSizer = wx.StaticBoxSizer(self.listBoxElse, wx.VERTICAL) 00515 listElseSizer.Add(item = self.itemListElse, proportion = 1, 00516 flag = wx.EXPAND) 00517 00518 btnSizer = wx.StdDialogButtonSizer() 00519 btnSizer.AddButton(self.btnCancel) 00520 btnSizer.AddButton(self.btnOk) 00521 btnSizer.Realize() 00522 00523 sizer.Add(item = condSizer, proportion = 0, 00524 flag = wx.EXPAND | wx.ALL, border = 3) 00525 sizer.Add(item = listIfSizer, proportion = 1, 00526 flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border = 3) 00527 sizer.Add(item = listElseSizer, proportion = 1, 00528 flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border = 3) 00529 sizer.Add(item = btnSizer, proportion=0, 00530 flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5) 00531 00532 self.panel.SetSizer(sizer) 00533 sizer.Fit(self.panel) 00534 00535 self.Layout() 00536 00537 def OnCheckItemIf(self, index, flag): 00538 """!Item in if-block checked/unchecked""" 00539 if flag is False: 00540 return 00541 00542 aId = int(self.itemListIf.GetItem(index, 0).GetText()) 00543 if aId in self.itemListElse.GetItems()['checked']: 00544 self.itemListElse.CheckItemById(aId, False) 00545 00546 def OnCheckItemElse(self, index, flag): 00547 """!Item in else-block checked/unchecked""" 00548 if flag is False: 00549 return 00550 00551 aId = int(self.itemListElse.GetItem(index, 0).GetText()) 00552 if aId in self.itemListIf.GetItems()['checked']: 00553 self.itemListIf.CheckItemById(aId, False) 00554 00555 def GetItems(self): 00556 """!Get items""" 00557 return { 'if' : self.itemListIf.GetItems(), 00558 'else' : self.itemListElse.GetItems() } 00559 00560 class ModelListCtrl(wx.ListCtrl, 00561 listmix.ListCtrlAutoWidthMixin, 00562 listmix.TextEditMixin, 00563 listmix.ColumnSorterMixin): 00564 def __init__(self, parent, columns, id = wx.ID_ANY, 00565 style = wx.LC_REPORT | wx.BORDER_NONE | 00566 wx.LC_SORT_ASCENDING |wx.LC_HRULES | 00567 wx.LC_VRULES, **kwargs): 00568 """!List of model variables""" 00569 self.parent = parent 00570 self.columns = columns 00571 self.shape = None 00572 try: 00573 self.frame = parent.parent 00574 except AttributeError: 00575 self.frame = None 00576 00577 wx.ListCtrl.__init__(self, parent, id = id, style = style, **kwargs) 00578 listmix.ListCtrlAutoWidthMixin.__init__(self) 00579 listmix.TextEditMixin.__init__(self) 00580 listmix.ColumnSorterMixin.__init__(self, 4) 00581 00582 i = 0 00583 for col in columns: 00584 self.InsertColumn(i, col) 00585 self.SetColumnWidth(i, wx.LIST_AUTOSIZE_USEHEADER) 00586 i += 1 00587 00588 self.itemDataMap = {} # requested by sorter 00589 self.itemCount = 0 00590 00591 self.Bind(wx.EVT_LIST_BEGIN_LABEL_EDIT, self.OnBeginEdit) 00592 self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnEndEdit) 00593 self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick) 00594 self.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.OnRightUp) #wxMSW 00595 self.Bind(wx.EVT_RIGHT_UP, self.OnRightUp) #wxGTK 00596 00597 def OnBeginEdit(self, event): 00598 """!Editing of item started""" 00599 event.Allow() 00600 00601 def OnEndEdit(self, event): 00602 """!Finish editing of item""" 00603 pass 00604 00605 def OnColClick(self, event): 00606 """!Click on column header (order by)""" 00607 event.Skip() 00608 00609 class VariableListCtrl(ModelListCtrl): 00610 def __init__(self, parent, columns, **kwargs): 00611 """!List of model variables""" 00612 ModelListCtrl.__init__(self, parent, columns, **kwargs) 00613 00614 self.SetColumnWidth(2, 200) # default value 00615 00616 def GetListCtrl(self): 00617 """!Used by ColumnSorterMixin""" 00618 return self 00619 00620 def GetData(self): 00621 """!Get list data""" 00622 return self.itemDataMap 00623 00624 def Populate(self, data): 00625 """!Populate the list""" 00626 self.itemDataMap = dict() 00627 i = 0 00628 for name, values in data.iteritems(): 00629 self.itemDataMap[i] = [name, values['type'], 00630 values.get('value', ''), 00631 values.get('description', '')] 00632 i += 1 00633 00634 self.itemCount = len(self.itemDataMap.keys()) 00635 self.DeleteAllItems() 00636 i = 0 00637 for name, vtype, value, desc in self.itemDataMap.itervalues(): 00638 index = self.InsertStringItem(sys.maxint, name) 00639 self.SetStringItem(index, 0, name) 00640 self.SetStringItem(index, 1, vtype) 00641 self.SetStringItem(index, 2, value) 00642 self.SetStringItem(index, 3, desc) 00643 self.SetItemData(index, i) 00644 i += 1 00645 00646 def Append(self, name, vtype, value, desc): 00647 """!Append new item to the list 00648 00649 @return None on success 00650 @return error string 00651 """ 00652 for iname, ivtype, ivalue, idesc in self.itemDataMap.itervalues(): 00653 if iname == name: 00654 return _("Variable <%s> already exists in the model. " 00655 "Adding variable failed.") % name 00656 00657 index = self.InsertStringItem(sys.maxint, name) 00658 self.SetStringItem(index, 0, name) 00659 self.SetStringItem(index, 1, vtype) 00660 self.SetStringItem(index, 2, value) 00661 self.SetStringItem(index, 3, desc) 00662 self.SetItemData(index, self.itemCount) 00663 00664 self.itemDataMap[self.itemCount] = [name, vtype, value, desc] 00665 self.itemCount += 1 00666 00667 return None 00668 00669 def OnRemove(self, event): 00670 """!Remove selected variable(s) from the model""" 00671 item = self.GetFirstSelected() 00672 while item != -1: 00673 self.DeleteItem(item) 00674 del self.itemDataMap[item] 00675 item = self.GetFirstSelected() 00676 self.parent.UpdateModelVariables() 00677 00678 event.Skip() 00679 00680 def OnRemoveAll(self, event): 00681 """!Remove all variable(s) from the model""" 00682 dlg = wx.MessageBox(parent=self, 00683 message=_("Do you want to delete all variables from " 00684 "the model?"), 00685 caption=_("Delete variables"), 00686 style=wx.YES_NO | wx.CENTRE) 00687 if dlg != wx.YES: 00688 return 00689 00690 self.DeleteAllItems() 00691 self.itemDataMap = dict() 00692 00693 self.parent.UpdateModelVariables() 00694 00695 def OnEndEdit(self, event): 00696 """!Finish editing of item""" 00697 itemIndex = event.GetIndex() 00698 columnIndex = event.GetColumn() 00699 nameOld = self.GetItem(itemIndex, 0).GetText() 00700 00701 if columnIndex == 0: # TODO 00702 event.Veto() 00703 00704 self.itemDataMap[itemIndex][columnIndex] = event.GetText() 00705 00706 self.parent.UpdateModelVariables() 00707 00708 def OnReload(self, event): 00709 """!Reload list of variables""" 00710 self.Populate(self.parent.parent.GetModel().GetVariables()) 00711 00712 def OnRightUp(self, event): 00713 """!Mouse right button up""" 00714 if not hasattr(self, "popupID1"): 00715 self.popupID1 = wx.NewId() 00716 self.popupID2 = wx.NewId() 00717 self.popupID3 = wx.NewId() 00718 self.Bind(wx.EVT_MENU, self.OnRemove, id = self.popupID1) 00719 self.Bind(wx.EVT_MENU, self.OnRemoveAll, id = self.popupID2) 00720 self.Bind(wx.EVT_MENU, self.OnReload, id = self.popupID3) 00721 00722 # generate popup-menu 00723 menu = wx.Menu() 00724 menu.Append(self.popupID1, _("Delete selected")) 00725 menu.Append(self.popupID2, _("Delete all")) 00726 if self.GetFirstSelected() == -1: 00727 menu.Enable(self.popupID1, False) 00728 menu.Enable(self.popupID2, False) 00729 00730 menu.AppendSeparator() 00731 menu.Append(self.popupID3, _("Reload")) 00732 00733 self.PopupMenu(menu) 00734 menu.Destroy() 00735 00736 class ItemListCtrl(ModelListCtrl): 00737 def __init__(self, parent, columns, disablePopup = False, **kwargs): 00738 """!List of model actions""" 00739 self.disablePopup = disablePopup 00740 00741 ModelListCtrl.__init__(self, parent, columns, **kwargs) 00742 self.SetColumnWidth(1, 100) 00743 self.SetColumnWidth(2, 65) 00744 00745 def GetListCtrl(self): 00746 """!Used by ColumnSorterMixin""" 00747 return self 00748 00749 def GetData(self): 00750 """!Get list data""" 00751 return self.itemDataMap 00752 00753 def Populate(self, data): 00754 """!Populate the list""" 00755 self.itemDataMap = dict() 00756 00757 if self.shape: 00758 if isinstance(self.shape, ModelCondition): 00759 if self.GetName() == 'ElseBlockList': 00760 shapeItems = map(lambda x: x.GetId(), self.shape.GetItems()['else']) 00761 else: 00762 shapeItems = map(lambda x: x.GetId(), self.shape.GetItems()['if']) 00763 else: 00764 shapeItems = map(lambda x: x.GetId(), self.shape.GetItems()) 00765 else: 00766 shapeItems = list() 00767 00768 i = 0 00769 if len(self.columns) == 3: # ItemCheckList 00770 checked = list() 00771 for action in data: 00772 if isinstance(action, ModelData) or \ 00773 action == self.shape: 00774 continue 00775 00776 if len(self.columns) == 3: 00777 self.itemDataMap[i] = [str(action.GetId()), 00778 action.GetName(), 00779 action.GetLog()] 00780 aId = action.GetBlockId() 00781 if action.GetId() in shapeItems: 00782 checked.append(aId) 00783 else: 00784 checked.append(None) 00785 else: 00786 bId = action.GetBlockId() 00787 if not bId: 00788 bId = '' 00789 self.itemDataMap[i] = [str(action.GetId()), 00790 action.GetName(), 00791 ','.join(map(str, bId)), 00792 action.GetLog()] 00793 00794 i += 1 00795 00796 self.itemCount = len(self.itemDataMap.keys()) 00797 self.DeleteAllItems() 00798 i = 0 00799 if len(self.columns) == 3: 00800 for aid, name, desc in self.itemDataMap.itervalues(): 00801 index = self.InsertStringItem(sys.maxint, aid) 00802 self.SetStringItem(index, 0, aid) 00803 self.SetStringItem(index, 1, name) 00804 self.SetStringItem(index, 2, desc) 00805 self.SetItemData(index, i) 00806 if checked[i]: 00807 self.CheckItem(index, True) 00808 i += 1 00809 else: 00810 for aid, name, inloop, desc in self.itemDataMap.itervalues(): 00811 index = self.InsertStringItem(sys.maxint, aid) 00812 self.SetStringItem(index, 0, aid) 00813 self.SetStringItem(index, 1, name) 00814 self.SetStringItem(index, 2, inloop) 00815 self.SetStringItem(index, 3, desc) 00816 self.SetItemData(index, i) 00817 i += 1 00818 00819 def OnRemove(self, event): 00820 """!Remove selected action(s) from the model""" 00821 model = self.frame.GetModel() 00822 canvas = self.frame.GetCanvas() 00823 00824 item = self.GetFirstSelected() 00825 while item != -1: 00826 self.DeleteItem(item) 00827 del self.itemDataMap[item] 00828 00829 aId = self.GetItem(item, 0).GetText() 00830 action = model.GetItem(int(aId)) 00831 if not action: 00832 item = self.GetFirstSelected() 00833 continue 00834 00835 model.RemoveItem(action) 00836 canvas.GetDiagram().RemoveShape(action) 00837 self.frame.ModelChanged() 00838 00839 item = self.GetFirstSelected() 00840 00841 canvas.Refresh() 00842 00843 event.Skip() 00844 00845 def OnRemoveAll(self, event): 00846 """!Remove all variable(s) from the model""" 00847 deleteDialog = wx.MessageBox(parent=self, 00848 message=_("Selected data records (%d) will permanently deleted " 00849 "from table. Do you want to delete them?") % \ 00850 (len(self.listOfSQLStatements)), 00851 caption=_("Delete records"), 00852 style=wx.YES_NO | wx.CENTRE) 00853 if deleteDialog != wx.YES: 00854 return False 00855 00856 self.DeleteAllItems() 00857 self.itemDataMap = dict() 00858 00859 self.parent.UpdateModelVariables() 00860 00861 def OnEndEdit(self, event): 00862 """!Finish editing of item""" 00863 itemIndex = event.GetIndex() 00864 columnIndex = event.GetColumn() 00865 00866 self.itemDataMap[itemIndex][columnIndex] = event.GetText() 00867 00868 aId = int(self.GetItem(itemIndex, 0).GetText()) 00869 action = self.frame.GetModel().GetItem(aId) 00870 if not action: 00871 event.Veto() 00872 if columnIndex == 0: 00873 action.SetId(int(event.GetText())) 00874 00875 self.frame.ModelChanged() 00876 00877 def OnReload(self, event = None): 00878 """!Reload list of actions""" 00879 self.Populate(self.frame.GetModel().GetItems()) 00880 00881 def OnRightUp(self, event): 00882 """!Mouse right button up""" 00883 if self.disablePopup: 00884 return 00885 00886 if not hasattr(self, "popupID1"): 00887 self.popupID1 = wx.NewId() 00888 self.popupID2 = wx.NewId() 00889 self.popupID3 = wx.NewId() 00890 self.popupID4 = wx.NewId() 00891 self.Bind(wx.EVT_MENU, self.OnRemove, id = self.popupID1) 00892 self.Bind(wx.EVT_MENU, self.OnRemoveAll, id = self.popupID2) 00893 self.Bind(wx.EVT_MENU, self.OnReload, id = self.popupID3) 00894 self.Bind(wx.EVT_MENU, self.OnNormalize, id = self.popupID4) 00895 00896 # generate popup-menu 00897 menu = wx.Menu() 00898 menu.Append(self.popupID1, _("Delete selected")) 00899 menu.Append(self.popupID2, _("Delete all")) 00900 if self.GetFirstSelected() == -1: 00901 menu.Enable(self.popupID1, False) 00902 menu.Enable(self.popupID2, False) 00903 00904 menu.AppendSeparator() 00905 menu.Append(self.popupID4, _("Normalize")) 00906 menu.Append(self.popupID3, _("Reload")) 00907 00908 self.PopupMenu(menu) 00909 menu.Destroy() 00910 00911 def OnNormalize(self, event): 00912 """!Update id of actions""" 00913 model = self.frame.GetModel() 00914 00915 aId = 1 00916 for item in model.GetItems(): 00917 item.SetId(aId) 00918 aId += 1 00919 00920 self.OnReload(None) 00921 self.frame.GetCanvas().Refresh() 00922 self.frame.ModelChanged() 00923 00924 class ItemCheckListCtrl(ItemListCtrl, listmix.CheckListCtrlMixin): 00925 def __init__(self, parent, shape, columns, window = None, **kwargs): 00926 self.parent = parent 00927 self.window = window 00928 00929 ItemListCtrl.__init__(self, parent, columns, disablePopup = True, **kwargs) 00930 listmix.CheckListCtrlMixin.__init__(self) 00931 self.SetColumnWidth(0, 50) 00932 00933 self.shape = shape 00934 00935 def OnBeginEdit(self, event): 00936 """!Disable editing""" 00937 event.Veto() 00938 00939 def OnCheckItem(self, index, flag): 00940 """!Item checked/unchecked""" 00941 name = self.GetName() 00942 if name == 'IfBlockList' and self.window: 00943 self.window.OnCheckItemIf(index, flag) 00944 elif name == 'ElseBlockList' and self.window: 00945 self.window.OnCheckItemElse(index, flag) 00946 00947 def GetItems(self): 00948 """!Get list of selected actions""" 00949 ids = { 'checked' : list(), 00950 'unchecked' : list() } 00951 for i in range(self.GetItemCount()): 00952 iId = int(self.GetItem(i, 0).GetText()) 00953 if self.IsChecked(i): 00954 ids['checked'].append(iId) 00955 else: 00956 ids['unchecked'].append(iId) 00957 00958 return ids 00959 00960 def CheckItemById(self, aId, flag): 00961 """!Check/uncheck given item by id""" 00962 for i in range(self.GetItemCount()): 00963 iId = int(self.GetItem(i, 0).GetText()) 00964 if iId == aId: 00965 self.CheckItem(i, flag) 00966 break