~ubuntu-branches/ubuntu/vivid/grass/vivid-proposed

« back to all changes in this revision

Viewing changes to gui/wxpython/gmodeler/dialogs.py

  • Committer: Package Import Robot
  • Author(s): Bas Couwenberg
  • Date: 2015-02-20 23:12:08 UTC
  • mfrom: (8.2.6 experimental)
  • Revision ID: package-import@ubuntu.com-20150220231208-1u6qvqm84v430b10
Tags: 7.0.0-1~exp1
* New upstream release.
* Update python-ctypes-ternary.patch to use if/else instead of and/or.
* Drop check4dev patch, rely on upstream check.
* Add build dependency on libpq-dev to grass-dev for libpq-fe.h.
* Drop patches applied upstream, refresh remaining patches.
* Update symlinks for images switched from jpg to png.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
"""!
 
1
"""
2
2
@package gmodeler.dialogs
3
3
 
4
4
@brief wxGUI Graphical Modeler - dialogs
15
15
 - dialogs::ItemListCtrl
16
16
 - dialogs::ItemCheckListCtrl
17
17
 
18
 
(C) 2010-2011 by the GRASS Development Team
 
18
(C) 2010-2013 by the GRASS Development Team
19
19
 
20
20
This program is free software under the GNU General Public License
21
21
(>=v2). Read the file COPYING that comes with GRASS for details.
31
31
 
32
32
from core                 import globalvar
33
33
from core                 import utils
34
 
from gui_core.widgets     import GNotebook
 
34
from core.utils import _
 
35
from gui_core.widgets     import SearchModuleWidget, SimpleValidator
35
36
from core.gcmd            import GError, EncodeString
36
 
from gui_core.dialogs     import ElementDialog, MapLayersDialog
37
 
from gui_core.ghelp       import SearchModuleWindow
 
37
from gui_core.dialogs     import SimpleDialog, MapLayersDialogForModeler
38
38
from gui_core.prompt      import GPromptSTC
39
 
from gui_core.forms       import CmdPanel
40
 
from gui_core.gselect     import Select
 
39
from gui_core.gselect     import Select, ElementSelect
41
40
from gmodeler.model       import *
 
41
from lmgr.menudata        import LayerManagerMenuData
42
42
 
43
43
from grass.script import task as gtask
44
44
 
45
 
class ModelDataDialog(ElementDialog):
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):
 
45
class ModelDataDialog(SimpleDialog):
 
46
    """Data item properties dialog"""
 
47
    def __init__(self, parent, shape, title = _("Data properties")):
49
48
        self.parent = parent
50
49
        self.shape = shape
51
50
        
52
51
        label, etype = self._getLabel()
53
 
        ElementDialog.__init__(self, parent, title, label = label, etype = etype)
 
52
        self.etype = etype
 
53
        SimpleDialog.__init__(self, parent, title)
54
54
                
55
 
        self.element = Select(parent = self.panel)
 
55
        self.element = Select(parent = self.panel,
 
56
                              validator = SimpleValidator(callback = self.ValidatorCallback))
56
57
        self.element.SetValue(shape.GetValue())
57
58
        
58
59
        self.Bind(wx.EVT_BUTTON, self.OnOK,     self.btnOK)
59
60
        self.Bind(wx.EVT_BUTTON, self.OnCancel, self.btnCancel)
60
 
        
61
 
        self.PostInit()
 
61
        if self.etype:
 
62
            self.typeSelect = ElementSelect(parent = self.panel,
 
63
                                            size = globalvar.DIALOG_GSELECT_SIZE)
 
64
            self.typeSelect.Bind(wx.EVT_CHOICE, self.OnType)
62
65
        
63
66
        if shape.GetValue():
64
67
            self.btnOK.Enable()
80
83
        return label, etype
81
84
    
82
85
    def _layout(self):
83
 
        """!Do layout"""
 
86
        """Do layout"""
 
87
        if self.etype:
 
88
            self.dataSizer.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
 
89
                                                    label = _("Type of element:")),
 
90
                               proportion = 0, flag = wx.ALL, border = 1)
 
91
            self.dataSizer.Add(item = self.typeSelect,
 
92
                               proportion = 0, flag = wx.ALL, border = 1)
 
93
        self.dataSizer.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
 
94
                                                label = _("Name of element:")),
 
95
                           proportion = 0, flag = wx.ALL, border = 1)
84
96
        self.dataSizer.Add(self.element, proportion=0,
85
97
                      flag=wx.EXPAND | wx.ALL, border=1)
86
98
        
87
99
        self.panel.SetSizer(self.sizer)
88
100
        self.sizer.Fit(self)
89
101
 
 
102
    def GetType(self):
 
103
        """Get element type"""
 
104
        if not self.etype:
 
105
            return
 
106
        return self.element.tcp.GetType()
 
107
 
 
108
    def OnType(self, event):
 
109
        """Select element type"""
 
110
        evalue = self.typeSelect.GetValue(event.GetString())
 
111
        self.element.SetType(evalue)
 
112
 
90
113
    def OnOK(self, event):
91
 
        """!Ok pressed"""
92
 
        self.shape.SetValue(self.GetElement())
 
114
        """Ok pressed"""
 
115
        self.shape.SetValue(self.element.GetValue())
93
116
        if self.etype:
94
117
            elem = self.GetType()
95
 
            if elem == 'rast':
 
118
            if elem == 'raster':
96
119
                self.shape.SetPrompt('raster')
97
 
            elif elem == 'vect':
 
120
            elif elem == 'vector':
98
121
                self.shape.SetPrompt('raster')
99
122
        
100
123
        self.parent.canvas.Refresh()
107
130
            self.Destroy()
108
131
    
109
132
    def OnCancel(self, event):
110
 
        """!Cancel pressed"""
 
133
        """Cancel pressed"""
111
134
        self.shape.SetPropDialog(None)
112
135
        if self.IsModal():
113
136
            event.Skip()
115
138
            self.Destroy()
116
139
 
117
140
class ModelSearchDialog(wx.Dialog):
118
 
    def __init__(self, parent, id = wx.ID_ANY, title = _("Add new GRASS module to the model"),
 
141
    def __init__(self, parent, title = _("Add GRASS command to the model"),
119
142
                 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
120
 
        """!Graphical modeler module search window
 
143
        """Graphical modeler module search window
121
144
        
122
 
        @param parent parent window
123
 
        @param id window id
124
 
        @param title window title
125
 
        @param kwargs wx.Dialogs' arguments
 
145
        :param parent: parent window
 
146
        :param id: window id
 
147
        :param title: window title
 
148
        :param kwargs: wx.Dialogs' arguments
126
149
        """
127
150
        self.parent = parent
128
151
        
129
 
        wx.Dialog.__init__(self, parent = parent, id = id, title = title, **kwargs)
 
152
        wx.Dialog.__init__(self, parent = parent, id = wx.ID_ANY, title = title, **kwargs)
130
153
        self.SetName("ModelerDialog")
131
 
        self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
 
154
        self.SetIcon(wx.Icon(os.path.join(globalvar.ICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
132
155
        
 
156
        self._command = None
133
157
        self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
134
158
        
135
159
        self.cmdBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
136
160
                                   label=" %s " % _("Command"))
137
 
        
138
 
        self.cmd_prompt = GPromptSTC(parent = self)
139
 
        self.search = SearchModuleWindow(parent = self.panel, cmdPrompt = self.cmd_prompt, showTip = True)
 
161
        self.labelBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
 
162
                                   label=" %s " % _("Label and comment"))
 
163
        
 
164
        # menu data for search widget and prompt
 
165
        menuModel = LayerManagerMenuData()
 
166
        
 
167
        self.cmd_prompt = GPromptSTC(parent = self, menuModel = menuModel.GetModel())
 
168
        self.cmd_prompt.promptRunCmd.connect(self.OnCommand)
 
169
        self.cmd_prompt.commandSelected.connect(lambda command: self.label.SetValue(command))
 
170
        self.search = SearchModuleWidget(parent = self.panel,
 
171
                                         model = menuModel.GetModel(),
 
172
                                         showTip = True)
 
173
        self.search.moduleSelected.connect(lambda name:
 
174
                                           self.cmd_prompt.SetTextAndFocus(name + ' '))
140
175
        wx.CallAfter(self.cmd_prompt.SetFocus)
141
176
        
142
 
        # get commands
143
 
        items = self.cmd_prompt.GetCommandItems()
 
177
        self.label = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY)
 
178
        self.comment = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY, style =  wx.TE_MULTILINE)
144
179
        
145
180
        self.btnCancel = wx.Button(self.panel, wx.ID_CANCEL)
146
181
        self.btnOk     = wx.Button(self.panel, wx.ID_OK)
147
182
        self.btnOk.SetDefault()
148
 
        self.btnOk.Enable(False)
149
183
 
150
 
        self.cmd_prompt.Bind(wx.EVT_KEY_UP, self.OnText)
151
 
        self.search.searchChoice.Bind(wx.EVT_CHOICE, self.OnText)
152
184
        self.Bind(wx.EVT_BUTTON, self.OnOk, self.btnOk)
 
185
        self.Bind(wx.EVT_BUTTON, self.OnCancel, self.btnCancel)
153
186
        
154
187
        self._layout()
155
188
        
156
 
        self.SetSize((500, 275))
157
 
        
 
189
        self.SetSize((500, -1))
 
190
 
158
191
    def _layout(self):
159
192
        cmdSizer = wx.StaticBoxSizer(self.cmdBox, wx.VERTICAL)
160
193
        cmdSizer.Add(item = self.cmd_prompt, proportion = 1,
161
194
                     flag = wx.EXPAND)
 
195
        labelSizer = wx.StaticBoxSizer(self.labelBox, wx.VERTICAL)
 
196
        gridSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
 
197
        gridSizer.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
 
198
                                           label = _("Label:")),
 
199
                      flag = wx.ALIGN_CENTER_VERTICAL, pos = (0, 0))
 
200
        gridSizer.Add(item = self.label, pos = (0, 1), flag =  wx.EXPAND)
 
201
        gridSizer.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
 
202
                                           label = _("Comment:")),
 
203
                      flag = wx.ALIGN_CENTER_VERTICAL, pos = (1, 0))
 
204
        gridSizer.Add(item = self.comment, pos = (1, 1), flag =  wx.EXPAND)
 
205
        gridSizer.AddGrowableCol(1)
 
206
        labelSizer.Add(item = gridSizer, proportion = 1, flag = wx.EXPAND)
162
207
        
163
208
        btnSizer = wx.StdDialogButtonSizer()
164
209
        btnSizer.AddButton(self.btnCancel)
170
215
                      flag = wx.EXPAND | wx.ALL, border = 3)
171
216
        mainSizer.Add(item = cmdSizer, proportion = 1,
172
217
                      flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, border = 3)
 
218
        mainSizer.Add(item = labelSizer, proportion = 1,
 
219
                      flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, border = 3)
173
220
        mainSizer.Add(item = btnSizer, proportion = 0,
174
221
                      flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
175
222
        
176
223
        self.panel.SetSizer(mainSizer)
177
 
        mainSizer.Fit(self.panel)
 
224
        mainSizer.Fit(self)
178
225
        
179
226
        self.Layout()
180
227
 
181
228
    def GetPanel(self):
182
 
        """!Get dialog panel"""
 
229
        """Get dialog panel"""
183
230
        return self.panel
184
231
 
185
 
    def GetCmd(self):
186
 
        """!Get command"""
 
232
    def _getCmd(self):
187
233
        line = self.cmd_prompt.GetCurLine()[0].strip()
188
234
        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
 
            
 
235
            cmd = list()
 
236
        else:
 
237
            try:
 
238
                cmd = utils.split(str(line))
 
239
            except UnicodeError:
 
240
                cmd = utils.split(EncodeString((line)))
196
241
        return cmd
 
242
 
 
243
    def GetCmd(self):
 
244
        """Get command"""
 
245
        return self._command
 
246
 
 
247
    def GetLabel(self):
 
248
        """Get label and comment"""
 
249
        return self.label.GetValue(), self.comment.GetValue()
197
250
    
198
 
    def OnOk(self, event):
199
 
        """!Button 'OK' pressed"""
200
 
        self.btnOk.SetFocus()
201
 
        cmd = self.GetCmd()
202
 
        
 
251
    def ValidateCmd(self, cmd):
203
252
        if len(cmd) < 1:
204
253
            GError(parent = self,
205
254
                   message = _("Command not defined.\n\n"
206
255
                               "Unable to add new action to the model."))
207
 
            return
 
256
            return False
208
257
        
209
258
        if cmd[0] not in globalvar.grassCmd:
210
259
            GError(parent = self,
211
260
                   message = _("'%s' is not a GRASS module.\n\n"
212
261
                               "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()
 
262
            return False
 
263
        return True
 
264
 
 
265
    def OnCommand(self, cmd):
 
266
        """Command in prompt confirmed"""
 
267
        if self.ValidateCmd(cmd):
 
268
            self._command = cmd
 
269
            self.EndModal(wx.ID_OK)
 
270
 
 
271
    def OnOk(self, event):
 
272
        """Button 'OK' pressed"""
 
273
        cmd = self._getCmd()
 
274
        if self.ValidateCmd(cmd):
 
275
            self._command = cmd
 
276
            self.EndModal(wx.ID_OK)
 
277
 
 
278
    def OnCancel(self, event):
 
279
        """Cancel pressed, close window"""
 
280
        self.Hide()
236
281
        
237
282
    def Reset(self):
238
 
        """!Reset dialog"""
 
283
        """Reset dialog"""
239
284
        self.search.Reset()
 
285
        self.label.SetValue('')
 
286
        self.comment.SetValue('')
240
287
        self.cmd_prompt.OnCmdErase(None)
241
 
        self.btnOk.Enable(False)
242
288
        self.cmd_prompt.SetFocus()
243
289
 
244
290
class ModelRelationDialog(wx.Dialog):
245
 
    """!Relation properties dialog"""
 
291
    """Relation properties dialog"""
246
292
    def __init__(self, parent, shape, id = wx.ID_ANY, title = _("Relation properties"),
247
293
                 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
248
294
        self.parent = parent
255
301
        
256
302
        self.valid = True
257
303
        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))
 
304
        self.SetIcon(wx.Icon(os.path.join(globalvar.ICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
259
305
        
260
306
        self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
261
307
        
313
359
                                               label = _("Command:")),
314
360
                          pos = (0, 0))
315
361
            gridSizer.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
316
 
                                               label = shape.GetName()),
 
362
                                               label = shape.GetLabel()),
317
363
                          pos = (0, 1))
318
364
            gridSizer.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
319
365
                                               label = _("Option:")),
326
372
                      border = 5)
327
373
            
328
374
    def _getOptions(self):
329
 
        """!Get relevant options"""
 
375
        """Get relevant options"""
330
376
        items = []
331
377
        fromShape = self.shape.GetFrom()
332
378
        if not isinstance(fromShape, ModelData):
356
402
        return items
357
403
    
358
404
    def GetOption(self):
359
 
        """!Get selected option"""
 
405
        """Get selected option"""
360
406
        return self.option.GetStringSelection()
361
407
    
362
408
    def IsValid(self):
363
 
        """!Check if relation is valid"""
 
409
        """Check if relation is valid"""
364
410
        return self.valid
365
411
    
366
412
    def OnOption(self, event):
367
 
        """!Set option"""
 
413
        """Set option"""
368
414
        if event.GetString():
369
415
            self.btnOk.Enable()
370
416
        else:
371
417
            self.btnOk.Enable(False)
372
418
 
373
419
class ModelItemDialog(wx.Dialog):
374
 
    """!Abstract item properties dialog"""
 
420
    """Abstract item properties dialog"""
375
421
    def __init__(self, parent, shape, title, id = wx.ID_ANY,
376
422
                 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
377
423
        self.parent = parent
384
430
        self.condBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
385
431
                                    label=" %s " % _("Condition"))
386
432
        self.condText = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY,
387
 
                                    value = shape.GetText())
 
433
                                    value = shape.GetLabel())
388
434
        
389
435
        self.itemList = ItemCheckListCtrl(parent = self.panel,
390
 
                                          window = self,
391
 
                                          columns = [_("ID"), _("Name"),
 
436
                                          columns = [_("Label"),
392
437
                                                     _("Command")],
393
 
                                          shape = shape)
 
438
                                          shape = shape,
 
439
                                          frame = parent)
 
440
        
394
441
        self.itemList.Populate(self.parent.GetModel().GetItems())
395
442
        
396
443
        self.btnCancel = wx.Button(parent = self.panel, id = wx.ID_CANCEL)
398
445
        self.btnOk.SetDefault()
399
446
        
400
447
    def _layout(self):
401
 
        """!Do layout (virtual method)"""
 
448
        """Do layout (virtual method)"""
402
449
        pass
403
450
    
404
451
    def GetCondition(self):
405
 
        """!Get loop condition"""
 
452
        """Get loop condition"""
406
453
        return self.condText.GetValue()
407
454
 
408
455
class ModelLoopDialog(ModelItemDialog):
409
 
    """!Loop properties dialog"""
 
456
    """Loop properties dialog"""
410
457
    def __init__(self, parent, shape, id = wx.ID_ANY, title = _("Loop properties"),
411
458
                 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
412
459
        ModelItemDialog.__init__(self, parent, shape, title,
425
472
        self.SetSize((500, 400))
426
473
        
427
474
    def _layout(self):
428
 
        """!Do layout"""
 
475
        """Do layout"""
429
476
        sizer = wx.BoxSizer(wx.VERTICAL)
430
477
        
431
478
        condSizer = wx.StaticBoxSizer(self.condBox, wx.HORIZONTAL)
456
503
        self.Layout()
457
504
        
458
505
    def GetItems(self):
459
 
        """!Get list of selected actions"""
 
506
        """Get list of selected actions"""
460
507
        return self.itemList.GetItems()
461
508
 
462
509
    def OnSeries(self, event):
463
 
        """!Define map series as condition"""
464
 
        dialog = MapLayersDialog(parent = self, title = _("Define series of maps"), modeler = True)
 
510
        """Define map series as condition"""
 
511
        dialog = MapLayersDialogForModeler(parent = self, title = _("Define series of maps"))
465
512
        if dialog.ShowModal() != wx.ID_OK:
466
513
            dialog.Destroy()
467
514
            return
475
522
        dialog.Destroy()
476
523
 
477
524
class ModelConditionDialog(ModelItemDialog):
478
 
    """!Condition properties dialog"""
 
525
    """Condition properties dialog"""
479
526
    def __init__(self, parent, shape, id = wx.ID_ANY, title = _("If-else properties"),
480
527
                 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
481
528
        ModelItemDialog.__init__(self, parent, shape, title,
489
536
        self.listBoxElse = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
490
537
                                        label=" %s " % _("List of items in 'else' block"))
491
538
        self.itemListElse = ItemCheckListCtrl(parent = self.panel,
492
 
                                              window = self,
493
 
                                              columns = [_("ID"), _("Name"),
 
539
                                              columns = [_("Label"),
494
540
                                                         _("Command")],
495
 
                                              shape = shape)
 
541
                                              shape = shape, frame = parent)
496
542
        self.itemListElse.SetName('ElseBlockList')
497
543
        self.itemListElse.Populate(self.parent.GetModel().GetItems())
498
544
        
501
547
        self.SetSize((500, 400))
502
548
        
503
549
    def _layout(self):
504
 
        """!Do layout"""
 
550
        """Do layout"""
505
551
        sizer = wx.BoxSizer(wx.VERTICAL)
506
552
        
507
553
        condSizer = wx.StaticBoxSizer(self.condBox, wx.VERTICAL)
535
581
        self.Layout()
536
582
 
537
583
    def OnCheckItemIf(self, index, flag):
538
 
        """!Item in if-block checked/unchecked"""
 
584
        """Item in if-block checked/unchecked"""
539
585
        if flag is False:
540
586
            return
541
587
        
544
590
            self.itemListElse.CheckItemById(aId, False)
545
591
            
546
592
    def OnCheckItemElse(self, index, flag):
547
 
        """!Item in else-block checked/unchecked"""
 
593
        """Item in else-block checked/unchecked"""
548
594
        if flag is False:
549
595
            return
550
596
        
553
599
            self.itemListIf.CheckItemById(aId, False)
554
600
        
555
601
    def GetItems(self):
556
 
        """!Get items"""
 
602
        """Get items"""
557
603
        return { 'if'   : self.itemListIf.GetItems(),
558
604
                 'else' : self.itemListElse.GetItems() }
559
605
 
560
606
class ModelListCtrl(wx.ListCtrl,
561
607
                    listmix.ListCtrlAutoWidthMixin,
562
 
                    listmix.TextEditMixin,
563
 
                    listmix.ColumnSorterMixin):
564
 
    def __init__(self, parent, columns, id = wx.ID_ANY,
 
608
                    listmix.TextEditMixin):
 
609
    def __init__(self, parent, columns, frame, id = wx.ID_ANY, columnsNotEditable = [],
565
610
                 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"""
 
611
                 wx.LC_HRULES | wx.LC_VRULES, **kwargs):
 
612
        """List of model variables"""
569
613
        self.parent = parent
570
614
        self.columns = columns
571
615
        self.shape = None
572
 
        try:
573
 
            self.frame  = parent.parent
574
 
        except AttributeError:
575
 
            self.frame = None
576
 
        
 
616
        self.frame  = frame
 
617
        self.columnNotEditable = columnsNotEditable
 
618
 
577
619
        wx.ListCtrl.__init__(self, parent, id = id, style = style, **kwargs)
578
620
        listmix.ListCtrlAutoWidthMixin.__init__(self)
579
621
        listmix.TextEditMixin.__init__(self)
580
 
        listmix.ColumnSorterMixin.__init__(self, 4)
581
 
        
 
622
 
582
623
        i = 0
583
624
        for col in columns:
584
625
            self.InsertColumn(i, col)
595
636
        self.Bind(wx.EVT_RIGHT_UP, self.OnRightUp)            #wxGTK
596
637
                
597
638
    def OnBeginEdit(self, event):
598
 
        """!Editing of item started"""
599
 
        event.Allow()
 
639
        """Editing of item started"""
 
640
        if self.columnNotEditable and event.m_col in self.columnNotEditable:
 
641
            event.Veto()
 
642
            self.SetItemState(event.m_itemIndex,
 
643
                              wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED | wx.LIST_STATE_FOCUSED)
 
644
        else:
 
645
            event.Allow()
600
646
 
601
647
    def OnEndEdit(self, event):
602
 
        """!Finish editing of item"""
 
648
        """Finish editing of item"""
603
649
        pass
604
650
    
 
651
    def GetListCtrl(self):
 
652
        """Used by ColumnSorterMixin"""
 
653
        return self
 
654
    
605
655
    def OnColClick(self, event):
606
 
        """!Click on column header (order by)"""
 
656
        """Click on column header (order by)"""
607
657
        event.Skip()
608
658
 
609
659
class VariableListCtrl(ModelListCtrl):
610
660
    def __init__(self, parent, columns, **kwargs):
611
 
        """!List of model variables"""
 
661
        """List of model variables"""
612
662
        ModelListCtrl.__init__(self, parent, columns, **kwargs)
613
663
 
614
664
        self.SetColumnWidth(2, 200) # default value
615
665
 
616
 
    def GetListCtrl(self):
617
 
        """!Used by ColumnSorterMixin"""
618
 
        return self
619
 
    
620
666
    def GetData(self):
621
 
        """!Get list data"""
 
667
        """Get list data"""
622
668
        return self.itemDataMap
623
669
    
624
670
    def Populate(self, data):
625
 
        """!Populate the list"""
 
671
        """Populate the list"""
626
672
        self.itemDataMap = dict()
627
673
        i = 0
628
674
        for name, values in data.iteritems():
644
690
            i += 1
645
691
        
646
692
    def Append(self, name, vtype, value, desc):
647
 
        """!Append new item to the list
 
693
        """Append new item to the list
648
694
 
649
 
        @return None on success
650
 
        @return error string
 
695
        :return: None on success
 
696
        :return: error string
651
697
        """
652
698
        for iname, ivtype, ivalue, idesc in self.itemDataMap.itervalues():
653
699
            if iname == name:
667
713
        return None
668
714
 
669
715
    def OnRemove(self, event):
670
 
        """!Remove selected variable(s) from the model"""
 
716
        """Remove selected variable(s) from the model"""
671
717
        item = self.GetFirstSelected()
672
718
        while item != -1:
673
719
            self.DeleteItem(item)
678
724
        event.Skip()
679
725
        
680
726
    def OnRemoveAll(self, event):
681
 
        """!Remove all variable(s) from the model"""
 
727
        """Remove all variable(s) from the model"""
682
728
        dlg = wx.MessageBox(parent=self,
683
729
                            message=_("Do you want to delete all variables from "
684
730
                                      "the model?"),
693
739
        self.parent.UpdateModelVariables()
694
740
        
695
741
    def OnEndEdit(self, event):
696
 
        """!Finish editing of item"""
 
742
        """Finish editing of item"""
697
743
        itemIndex = event.GetIndex()
698
744
        columnIndex = event.GetColumn()
699
745
        nameOld = self.GetItem(itemIndex, 0).GetText()
706
752
        self.parent.UpdateModelVariables()
707
753
 
708
754
    def OnReload(self, event):
709
 
        """!Reload list of variables"""
 
755
        """Reload list of variables"""
710
756
        self.Populate(self.parent.parent.GetModel().GetVariables())
711
757
 
712
758
    def OnRightUp(self, event):
713
 
        """!Mouse right button up"""
 
759
        """Mouse right button up"""
714
760
        if not hasattr(self, "popupID1"):
715
761
            self.popupID1 = wx.NewId()
716
762
            self.popupID2 = wx.NewId()
734
780
        menu.Destroy()
735
781
 
736
782
class ItemListCtrl(ModelListCtrl):
737
 
    def __init__(self, parent, columns, disablePopup = False, **kwargs):
738
 
        """!List of model actions"""
 
783
    def __init__(self, parent, columns, frame, disablePopup = False, **kwargs):
 
784
        """List of model actions"""
739
785
        self.disablePopup = disablePopup
740
 
                
741
 
        ModelListCtrl.__init__(self, parent, columns, **kwargs)
742
 
        self.SetColumnWidth(1, 100)
 
786
 
 
787
        ModelListCtrl.__init__(self, parent, columns, frame, **kwargs)
 
788
        self.itemIdMap = list()
 
789
        
 
790
        self.SetColumnWidth(0, 100)
 
791
        self.SetColumnWidth(1, 75)
743
792
        self.SetColumnWidth(2, 65)
744
793
        
745
 
    def GetListCtrl(self):
746
 
        """!Used by ColumnSorterMixin"""
747
 
        return self
748
 
    
749
794
    def GetData(self):
750
 
        """!Get list data"""
 
795
        """Get list data"""
751
796
        return self.itemDataMap
752
797
    
753
798
    def Populate(self, data):
754
 
        """!Populate the list"""
 
799
        """Populate the list"""
755
800
        self.itemDataMap = dict()
 
801
        self.itemIdMap = list()
756
802
        
757
803
        if self.shape:
 
804
            items = self.frame.GetModel().GetItems(objType=ModelAction)
758
805
            if isinstance(self.shape, ModelCondition):
759
 
                if self.GetName() == 'ElseBlockList':
760
 
                    shapeItems = map(lambda x: x.GetId(), self.shape.GetItems()['else'])
 
806
                if self.GetLabel() == 'ElseBlockList':
 
807
                    shapeItems = map(lambda x: x.GetId(), self.shape.GetItems(items)['else'])
761
808
                else:
762
 
                    shapeItems = map(lambda x: x.GetId(), self.shape.GetItems()['if'])
 
809
                    shapeItems = map(lambda x: x.GetId(), self.shape.GetItems(items)['if'])
763
810
            else:
764
 
                shapeItems = map(lambda x: x.GetId(), self.shape.GetItems())
 
811
                shapeItems = map(lambda x: x.GetId(), self.shape.GetItems(items))
765
812
        else:
766
813
            shapeItems = list()
767
814
        
768
815
        i = 0
769
 
        if len(self.columns) == 3: # ItemCheckList
 
816
        if len(self.columns) == 2: # ItemCheckList
770
817
            checked = list()
771
818
        for action in data:
772
819
            if isinstance(action, ModelData) or \
773
820
                    action == self.shape:
774
821
                continue
775
822
            
776
 
            if len(self.columns) == 3:
777
 
                self.itemDataMap[i] = [str(action.GetId()),
778
 
                                       action.GetName(),
 
823
            self.itemIdMap.append(action.GetId())
 
824
            
 
825
            if len(self.columns) == 2:
 
826
                self.itemDataMap[i] = [action.GetLabel(),
779
827
                                       action.GetLog()]
780
828
                aId = action.GetBlockId()
781
829
                if action.GetId() in shapeItems:
785
833
            else:
786
834
                bId = action.GetBlockId()
787
835
                if not bId:
788
 
                    bId = ''
789
 
                self.itemDataMap[i] = [str(action.GetId()),
790
 
                                       action.GetName(),
791
 
                                       ','.join(map(str, bId)),
 
836
                    bId = _('No')
 
837
                else:
 
838
                    bId = _("Yes")
 
839
                self.itemDataMap[i] = [action.GetLabel(),
 
840
                                       bId,
792
841
                                       action.GetLog()]
793
842
            
794
843
            i += 1
796
845
        self.itemCount = len(self.itemDataMap.keys())
797
846
        self.DeleteAllItems()
798
847
        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)
 
848
        if len(self.columns) == 2:
 
849
            for name, desc in self.itemDataMap.itervalues():
 
850
                index = self.InsertStringItem(sys.maxint, str(i))
 
851
                self.SetStringItem(index, 0, name)
 
852
                self.SetStringItem(index, 1, desc)
805
853
                self.SetItemData(index, i)
806
854
                if checked[i]:
807
855
                    self.CheckItem(index, True)
808
856
                i += 1
809
857
        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)
 
858
            for name, inloop, desc in self.itemDataMap.itervalues():
 
859
                index = self.InsertStringItem(sys.maxint, str(i))
 
860
                self.SetStringItem(index, 0, name)
 
861
                self.SetStringItem(index, 1, inloop)
 
862
                self.SetStringItem(index, 2, desc)
816
863
                self.SetItemData(index, i)
817
864
                i += 1
818
865
                
819
866
    def OnRemove(self, event):
820
 
        """!Remove selected action(s) from the model"""
 
867
        """Remove selected action(s) from the model"""
821
868
        model = self.frame.GetModel()
822
869
        canvas = self.frame.GetCanvas()
823
870
        
826
873
            self.DeleteItem(item)
827
874
            del self.itemDataMap[item]
828
875
            
829
 
            aId = self.GetItem(item, 0).GetText()
830
 
            action = model.GetItem(int(aId))
 
876
            action = model.GetItem(item+1) # action indeces starts at 1
831
877
            if not action:
832
878
                item = self.GetFirstSelected()
833
879
                continue
834
880
            
835
 
            model.RemoveItem(action)
836
 
            canvas.GetDiagram().RemoveShape(action)
 
881
            canvas.RemoveShapes([action])
837
882
            self.frame.ModelChanged()
838
883
            
839
884
            item = self.GetFirstSelected()
842
887
        
843
888
        event.Skip()
844
889
    
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
890
    def OnEndEdit(self, event):
862
 
        """!Finish editing of item"""
 
891
        """Finish editing of item"""
863
892
        itemIndex = event.GetIndex()
864
893
        columnIndex = event.GetColumn()
865
 
        
866
894
        self.itemDataMap[itemIndex][columnIndex] = event.GetText()
867
 
        
868
 
        aId = int(self.GetItem(itemIndex, 0).GetText())
869
 
        action = self.frame.GetModel().GetItem(aId)
 
895
        action = self.frame.GetModel().GetItem(itemIndex + 1)
870
896
        if not action:
871
897
            event.Veto()
872
 
        if columnIndex == 0:
873
 
            action.SetId(int(event.GetText()))
874
 
        
 
898
            return
 
899
 
 
900
        action.SetLabel(label = event.GetText())
875
901
        self.frame.ModelChanged()
876
902
 
877
903
    def OnReload(self, event = None):
878
 
        """!Reload list of actions"""
879
 
        self.Populate(self.frame.GetModel().GetItems())
 
904
        """Reload list of actions"""
 
905
        self.Populate(self.frame.GetModel().GetItems(objType=ModelAction))
880
906
 
881
907
    def OnRightUp(self, event):
882
 
        """!Mouse right button up"""
 
908
        """Mouse right button up"""
883
909
        if self.disablePopup:
884
910
            return
885
911
        
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)
 
912
        if not hasattr(self, "popupId"):
 
913
            self.popupID = dict()
 
914
            self.popupID['remove'] = wx.NewId()
 
915
            self.popupID['reload'] = wx.NewId()
 
916
            self.Bind(wx.EVT_MENU, self.OnRemove,    id = self.popupID['remove'])
 
917
            self.Bind(wx.EVT_MENU, self.OnReload,    id = self.popupID['reload'])
895
918
 
896
919
        # generate popup-menu
897
920
        menu = wx.Menu()
898
 
        menu.Append(self.popupID1, _("Delete selected"))
899
 
        menu.Append(self.popupID2, _("Delete all"))
 
921
        menu.Append(self.popupID['remove'], _("Delete selected"))
900
922
        if self.GetFirstSelected() == -1:
901
 
            menu.Enable(self.popupID1, False)
902
 
            menu.Enable(self.popupID2, False)
903
 
        
 
923
            menu.Enable(self.popupID['remove'], False)
904
924
        menu.AppendSeparator()
905
 
        menu.Append(self.popupID4, _("Normalize"))
906
 
        menu.Append(self.popupID3, _("Reload"))
 
925
        menu.Append(self.popupID['reload'], _("Reload"))
907
926
        
908
927
        self.PopupMenu(menu)
909
928
        menu.Destroy()
910
929
    
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()
 
930
    def MoveItems(self, items, up):
 
931
        """Move items in the list
 
932
 
 
933
        :param items: list of items to move
 
934
        :param up: True to move up otherwise down
 
935
        """
 
936
        if len(items) < 1:
 
937
            return
 
938
        
 
939
        if items[0] == 0 and up:
 
940
            del items[0]
 
941
        if len(items) < 1:
 
942
            return
 
943
        
 
944
        if items[-1] == len(self.itemDataMap.keys())-1 and not up:
 
945
            del items[-1]
 
946
        if len(items) < 1:
 
947
            return
 
948
 
 
949
        model = self.frame.GetModel()        
 
950
        modelActions = model.GetItems(objType=ModelAction)
 
951
        idxList = dict()
 
952
        itemsToSelect = list()
 
953
        for i in items:
 
954
            if up:
 
955
                idx = i-1
 
956
            else:
 
957
                idx = i+1
 
958
            itemsToSelect.append(idx)
 
959
            idxList[model.GetItemIndex(modelActions[i])] = model.GetItemIndex(modelActions[idx])
 
960
        
 
961
        # reorganize model items
 
962
        model.ReorderItems(idxList)
 
963
        model.Normalize()
 
964
        self.Populate(model.GetItems(objType=ModelAction))
 
965
        
 
966
        # re-selected originaly selected item
 
967
        for item in itemsToSelect:
 
968
            self.SetItemState(item,  wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED | wx.LIST_STATE_FOCUSED)
923
969
 
924
970
class ItemCheckListCtrl(ItemListCtrl, listmix.CheckListCtrlMixin):
925
 
    def __init__(self, parent, shape, columns, window = None, **kwargs):
 
971
    def __init__(self, parent, shape, columns, frame, **kwargs):
926
972
        self.parent = parent
927
 
        self.window = window
 
973
        self.frame  = frame
928
974
        
929
 
        ItemListCtrl.__init__(self, parent, columns, disablePopup = True, **kwargs)
 
975
        ItemListCtrl.__init__(self, parent, columns, frame,
 
976
                              disablePopup = True, **kwargs)
930
977
        listmix.CheckListCtrlMixin.__init__(self)
931
 
        self.SetColumnWidth(0, 50)
 
978
        self.SetColumnWidth(0, 100)
932
979
        
933
980
        self.shape  = shape
934
981
        
935
982
    def OnBeginEdit(self, event):
936
 
        """!Disable editing"""
 
983
        """Disable editing"""
937
984
        event.Veto()
938
985
        
939
986
    def OnCheckItem(self, index, flag):
940
 
        """!Item checked/unchecked"""
941
 
        name = self.GetName()
 
987
        """Item checked/unchecked"""
 
988
        name = self.GetLabel()
942
989
        if name == 'IfBlockList' and self.window:
943
990
            self.window.OnCheckItemIf(index, flag)
944
991
        elif name == 'ElseBlockList' and self.window:
945
992
            self.window.OnCheckItemElse(index, flag)
946
993
        
947
994
    def GetItems(self):
948
 
        """!Get list of selected actions"""
 
995
        """Get list of selected actions"""
949
996
        ids = { 'checked'   : list(),
950
997
                'unchecked' : list() }
 
998
        
 
999
        # action ids start at 1
951
1000
        for i in range(self.GetItemCount()):
952
 
            iId = int(self.GetItem(i, 0).GetText())
953
1001
            if self.IsChecked(i):
954
 
                ids['checked'].append(iId)
 
1002
                ids['checked'].append(self.itemIdMap[i])
955
1003
            else:
956
 
                ids['unchecked'].append(iId)
 
1004
                ids['unchecked'].append(self.itemIdMap[i])
957
1005
            
958
1006
        return ids
959
1007
 
960
1008
    def CheckItemById(self, aId, flag):
961
 
        """!Check/uncheck given item by id"""
 
1009
        """Check/uncheck given item by id"""
962
1010
        for i in range(self.GetItemCount()):
963
1011
            iId = int(self.GetItem(i, 0).GetText())
964
1012
            if iId == aId: