|
@@ -17,6 +17,8 @@ Classes:
|
|
|
- PreferencesDialog
|
|
|
- PropertiesDialog
|
|
|
- ModelParamDialog
|
|
|
+ - VariablesDialog
|
|
|
+ - ValiablesListCtrl
|
|
|
|
|
|
(C) 2010 by the GRASS Development Team
|
|
|
This program is free software under the GNU General Public License
|
|
@@ -45,9 +47,10 @@ import globalvar
|
|
|
if not os.getenv("GRASS_WXBUNDLED"):
|
|
|
globalvar.CheckForWx()
|
|
|
import wx
|
|
|
-import wx.lib.ogl as ogl
|
|
|
-import wx.lib.flatnotebook as FN
|
|
|
-import wx.lib.colourselect as csel
|
|
|
+import wx.lib.ogl as ogl
|
|
|
+import wx.lib.flatnotebook as FN
|
|
|
+import wx.lib.colourselect as csel
|
|
|
+import wx.lib.mixins.listctrl as listmix
|
|
|
|
|
|
import menu
|
|
|
import menudata
|
|
@@ -74,6 +77,8 @@ class Model(object):
|
|
|
self.properties = { 'name' : _("model"),
|
|
|
'description' : _("Script generated by wxGUI Graphical Modeler."),
|
|
|
'author' : getpass.getuser() }
|
|
|
+ # model variables
|
|
|
+ self.variables = dict()
|
|
|
|
|
|
self.canvas = canvas
|
|
|
|
|
@@ -88,6 +93,14 @@ class Model(object):
|
|
|
def GetProperties(self):
|
|
|
"""!Get model properties"""
|
|
|
return self.properties
|
|
|
+
|
|
|
+ def GetVariables(self):
|
|
|
+ """!Get model variables"""
|
|
|
+ return self.variables
|
|
|
+
|
|
|
+ def SetVariables(self, data):
|
|
|
+ """!Set model variables"""
|
|
|
+ self.variables = data
|
|
|
|
|
|
def GetData(self):
|
|
|
"""!Return list of data"""
|
|
@@ -476,8 +489,10 @@ class ModelFrame(wx.Frame):
|
|
|
|
|
|
def OnModelVariables(self, event):
|
|
|
"""!Manage (define) model variables"""
|
|
|
- pass
|
|
|
-
|
|
|
+ dlg = VariablesDialog(parent = self, data = self.model.GetVariables())
|
|
|
+ dlg.CentreOnParent()
|
|
|
+ dlg.Show()
|
|
|
+
|
|
|
def OnDeleteData(self, event):
|
|
|
"""!Delete intermediate data"""
|
|
|
rast, vect, rast3d, msg = self.model.GetIntermediateData()
|
|
@@ -2015,6 +2030,7 @@ class ProcessModelFile:
|
|
|
self.data = list()
|
|
|
|
|
|
self._processProperties()
|
|
|
+ self._processVariables()
|
|
|
self._processActions()
|
|
|
self._processData()
|
|
|
|
|
@@ -2060,7 +2076,11 @@ class ProcessModelFile:
|
|
|
self.properties[name] = node.text
|
|
|
else:
|
|
|
self.properties[name] = ''
|
|
|
-
|
|
|
+
|
|
|
+ def _processVariables(self):
|
|
|
+ for node in self.root.findall('variable'):
|
|
|
+ pass
|
|
|
+
|
|
|
def _processActions(self):
|
|
|
"""!Process model file"""
|
|
|
for action in self.root.findall('action'):
|
|
@@ -2788,6 +2808,268 @@ class ModelParamDialog(wx.Dialog):
|
|
|
panel = menuform.cmdPanel(parent = self, id = wx.ID_ANY, task = task)
|
|
|
|
|
|
return panel
|
|
|
+
|
|
|
+class VariablesDialog(wx.Dialog, listmix.ColumnSorterMixin):
|
|
|
+ def __init__(self, parent, id = wx.ID_ANY, title = _("Manage model variables"),
|
|
|
+ style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
|
|
|
+ data = dict(), **kwargs):
|
|
|
+ """!Manage model variables dialog
|
|
|
+
|
|
|
+ @param parent
|
|
|
+ @param title dialog title
|
|
|
+ @param style
|
|
|
+ """
|
|
|
+ self.parent = parent
|
|
|
+
|
|
|
+ wx.Dialog.__init__(self, parent = parent, id = id, title = title,
|
|
|
+ style = style, **kwargs)
|
|
|
+
|
|
|
+ self.listBox = wx.StaticBox(parent = self, id = wx.ID_ANY,
|
|
|
+ label=" %s " % _("List of variables - right-click to delete"))
|
|
|
+
|
|
|
+ self.list = VariablesListCtrl(parent = self, id = wx.ID_ANY,
|
|
|
+ style = wx.LC_REPORT | wx.BORDER_NONE |
|
|
|
+ wx.LC_SORT_ASCENDING |wx.LC_HRULES |
|
|
|
+ wx.LC_VRULES)
|
|
|
+ if data:
|
|
|
+ self.list.Populate(data)
|
|
|
+
|
|
|
+ # sorter
|
|
|
+ listmix.ColumnSorterMixin.__init__(self, 2)
|
|
|
+
|
|
|
+ # add new category
|
|
|
+ self.addBox = wx.StaticBox(parent = self, id = wx.ID_ANY,
|
|
|
+ label = " %s " % _("Add new variable"))
|
|
|
+ self.name = wx.TextCtrl(parent = self, id = wx.ID_ANY, size = (150, -1))
|
|
|
+ wx.CallAfter(self.name.SetFocus)
|
|
|
+ self.type = wx.Choice(parent = self, id = wx.ID_ANY,
|
|
|
+ choices = [_("integer"),
|
|
|
+ _("float"),
|
|
|
+ _("string")])
|
|
|
+ self.value = wx.TextCtrl(parent = self, id = wx.ID_ANY, size = (150, -1))
|
|
|
+ self.desc = wx.TextCtrl(parent = self, id = wx.ID_ANY, size = (350, -1))
|
|
|
+
|
|
|
+ # buttons
|
|
|
+ self.btnCancel = wx.Button(parent = self, id = wx.ID_CANCEL)
|
|
|
+ self.btnCancel.SetToolTipString(_("Ignore changes and close dialog"))
|
|
|
+ self.btnOk = wx.Button(parent = self, id = wx.ID_OK)
|
|
|
+ self.btnOk.SetToolTipString(_("Apply changes and close dialog"))
|
|
|
+ self.btnOk.SetDefault()
|
|
|
+ self.btnAdd = wx.Button(parent = self, id = wx.ID_ADD)
|
|
|
+ self.btnAdd.SetToolTipString(_("Add new variable to the model"))
|
|
|
+ self.btnAdd.Enable(False)
|
|
|
+
|
|
|
+ # bindings
|
|
|
+ self.btnOk.Bind(wx.EVT_BUTTON, self.OnOK)
|
|
|
+ self.name.Bind(wx.EVT_TEXT, self.OnText)
|
|
|
+ self.value.Bind(wx.EVT_TEXT, self.OnText)
|
|
|
+ self.desc.Bind(wx.EVT_TEXT, self.OnText)
|
|
|
+ self.btnAdd.Bind(wx.EVT_BUTTON, self.OnAdd)
|
|
|
+
|
|
|
+ # list
|
|
|
+ self.list.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.OnRightUp) #wxMSW
|
|
|
+ self.list.Bind(wx.EVT_RIGHT_UP, self.OnRightUp) #wxGTK
|
|
|
+ # self.Bind(wx.EVT_LIST_BEGIN_LABEL_EDIT, self.OnBeginEdit, self.list)
|
|
|
+ # self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnEndEdit, self.list)
|
|
|
+ # self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick, self.list)
|
|
|
+
|
|
|
+ self._layout()
|
|
|
+
|
|
|
+ def _layout(self):
|
|
|
+ """!Layout dialog"""
|
|
|
+ listSizer = wx.StaticBoxSizer(self.listBox, wx.VERTICAL)
|
|
|
+ listSizer.Add(item = self.list, proportion = 1,
|
|
|
+ flag = wx.EXPAND)
|
|
|
+
|
|
|
+ addSizer = wx.StaticBoxSizer(self.addBox, wx.VERTICAL)
|
|
|
+ gridSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
|
|
|
+ gridSizer.AddGrowableCol(3)
|
|
|
+ gridSizer.Add(item = wx.StaticText(parent = self, id = wx.ID_ANY,
|
|
|
+ label = "%s:" % _("Name")),
|
|
|
+ flag = wx.ALIGN_CENTER_VERTICAL,
|
|
|
+ pos = (0, 0))
|
|
|
+ gridSizer.Add(item = self.name,
|
|
|
+ pos = (0, 1))
|
|
|
+ gridSizer.Add(item = wx.StaticText(parent = self, id = wx.ID_ANY,
|
|
|
+ label = "%s:" % _("Data type")),
|
|
|
+ flag = wx.ALIGN_CENTER_VERTICAL,
|
|
|
+ pos = (0, 2))
|
|
|
+ gridSizer.Add(item = self.type,
|
|
|
+ pos = (0, 3))
|
|
|
+ gridSizer.Add(item = wx.StaticText(parent = self, id = wx.ID_ANY,
|
|
|
+ label = "%s:" % _("Default value")),
|
|
|
+ flag = wx.ALIGN_CENTER_VERTICAL,
|
|
|
+ pos = (1, 0))
|
|
|
+ gridSizer.Add(item = self.value,
|
|
|
+ pos = (1, 1))
|
|
|
+ gridSizer.Add(item = wx.StaticText(parent = self, id = wx.ID_ANY,
|
|
|
+ label = "%s:" % _("Description")),
|
|
|
+ flag = wx.ALIGN_CENTER_VERTICAL,
|
|
|
+ pos = (2, 0))
|
|
|
+ gridSizer.Add(item = self.desc,
|
|
|
+ pos = (2, 1), span = (1, 3))
|
|
|
+ addSizer.Add(item = gridSizer)
|
|
|
+ addSizer.Add(item = self.btnAdd, proportion = 0,
|
|
|
+ flag = wx.TOP | wx.ALIGN_RIGHT, border = 5)
|
|
|
+
|
|
|
+ btnSizer = wx.StdDialogButtonSizer()
|
|
|
+ btnSizer.AddButton(self.btnCancel)
|
|
|
+ btnSizer.AddButton(self.btnOk)
|
|
|
+ btnSizer.Realize()
|
|
|
+
|
|
|
+ mainSizer = wx.BoxSizer(wx.VERTICAL)
|
|
|
+ mainSizer.Add(item = listSizer, proportion = 1,
|
|
|
+ flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
|
|
|
+ mainSizer.Add(item = addSizer, proportion = 0,
|
|
|
+ flag = wx.EXPAND | wx.ALIGN_CENTER |
|
|
|
+ wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
|
|
|
+ mainSizer.Add(item = btnSizer, proportion = 0,
|
|
|
+ flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
|
|
|
+
|
|
|
+ self.SetSizer(mainSizer)
|
|
|
+ mainSizer.Fit(self)
|
|
|
+ self.SetAutoLayout(True)
|
|
|
+
|
|
|
+ # set min size for dialog
|
|
|
+ self.SetMinSize(self.GetBestSize())
|
|
|
+
|
|
|
+ def GetListCtrl(self):
|
|
|
+ """!Used by ColumnSorterMixin"""
|
|
|
+ return self.list
|
|
|
+
|
|
|
+ def OnText(self, event):
|
|
|
+ """!Text entered"""
|
|
|
+ if self.name.GetValue():
|
|
|
+ self.btnAdd.Enable()
|
|
|
+ else:
|
|
|
+ self.btnAdd.Enable(False)
|
|
|
+
|
|
|
+ def OnAdd(self, event):
|
|
|
+ """!Add new variable to the list"""
|
|
|
+ msg = self.list.Append(self.name.GetValue(),
|
|
|
+ self.type.GetStringSelection(),
|
|
|
+ self.value.GetValue(),
|
|
|
+ self.desc.GetValue())
|
|
|
+ self.name.SetValue('')
|
|
|
+ self.name.SetFocus()
|
|
|
+
|
|
|
+ if msg:
|
|
|
+ GMessage(parent = self,
|
|
|
+ message = msg)
|
|
|
+ else:
|
|
|
+ self.type.SetSelection(0)
|
|
|
+ self.value.SetValue('')
|
|
|
+ self.desc.SetValue('')
|
|
|
+
|
|
|
+ def OnRightUp(self, event):
|
|
|
+ """!Mouse right button up"""
|
|
|
+ if not hasattr(self, "popupID1"):
|
|
|
+ self.popupID1 = wx.NewId()
|
|
|
+ self.popupID2 = wx.NewId()
|
|
|
+ self.popupID3 = wx.NewId()
|
|
|
+ self.Bind(wx.EVT_MENU, self.list.OnRemove, id = self.popupID1)
|
|
|
+ self.Bind(wx.EVT_MENU, self.list.OnRemoveAll, id = self.popupID2)
|
|
|
+ self.Bind(wx.EVT_MENU, self.OnReload, id = self.popupID3)
|
|
|
+
|
|
|
+ # generate popup-menu
|
|
|
+ menu = wx.Menu()
|
|
|
+ menu.Append(self.popupID1, _("Delete selected"))
|
|
|
+ menu.Append(self.popupID2, _("Delete all"))
|
|
|
+ if self.list.GetFirstSelected() == -1:
|
|
|
+ menu.Enable(self.popupID1, False)
|
|
|
+ menu.Enable(self.popupID2, False)
|
|
|
+
|
|
|
+ menu.AppendSeparator()
|
|
|
+ menu.Append(self.popupID3, _("Reload"))
|
|
|
+
|
|
|
+ self.PopupMenu(menu)
|
|
|
+ menu.Destroy()
|
|
|
+
|
|
|
+ def OnReload(self, event):
|
|
|
+ """!Reload list of variables"""
|
|
|
+ self.list.Populate(self.parent.GetModel().GetVariables())
|
|
|
+
|
|
|
+ def OnOK(self, event):
|
|
|
+ """!Store variables to the model"""
|
|
|
+ self.parent.GetModel().SetVariables(self.list.GetData())
|
|
|
+ self.Destroy()
|
|
|
+
|
|
|
+class VariablesListCtrl(wx.ListCtrl,
|
|
|
+ listmix.ListCtrlAutoWidthMixin,
|
|
|
+ listmix.TextEditMixin):
|
|
|
+ def __init__(self, parent, id = wx.ID_ANY, **kwargs):
|
|
|
+ """!List of model variables"""
|
|
|
+ self.parent = parent
|
|
|
+
|
|
|
+ wx.ListCtrl.__init__(self, parent, id = id, **kwargs)
|
|
|
+ listmix.ListCtrlAutoWidthMixin.__init__(self)
|
|
|
+ listmix.TextEditMixin.__init__(self)
|
|
|
+
|
|
|
+ self.InsertColumn(0, _("Name"))
|
|
|
+ self.InsertColumn(1, _("Data type"))
|
|
|
+ self.InsertColumn(2, _("Default value"))
|
|
|
+ self.InsertColumn(3, _("Description"))
|
|
|
+ for i in range(0, self.GetColumnCount()):
|
|
|
+ self.SetColumnWidth(i, wx.LIST_AUTOSIZE_USEHEADER)
|
|
|
+
|
|
|
+ self.itemData = {} # requested by sorter
|
|
|
+ self.itemCount = 0
|
|
|
+
|
|
|
+ def GetData(self):
|
|
|
+ """!Get list data"""
|
|
|
+ return self.itemData
|
|
|
+
|
|
|
+ def Populate(self, data):
|
|
|
+ """!Populate the list"""
|
|
|
+ self.itemData = copy.deepcopy(data)
|
|
|
+ self.itemCount = len(self.itemData.keys())
|
|
|
+ self.DeleteAllItems()
|
|
|
+ i = 0
|
|
|
+ for name, vtype, value, desc in self.itemData.itervalues():
|
|
|
+ index = self.InsertStringItem(sys.maxint, name)
|
|
|
+ self.SetStringItem(index, 0, name)
|
|
|
+ self.SetStringItem(index, 1, vtype)
|
|
|
+ self.SetStringItem(index, 2, value)
|
|
|
+ self.SetStringItem(index, 3, desc)
|
|
|
+ self.SetItemData(index, i)
|
|
|
+ i += 1
|
|
|
+
|
|
|
+ def Append(self, name, vtype, value, desc):
|
|
|
+ """!Append new item to the list
|
|
|
+
|
|
|
+ @return None on success
|
|
|
+ @return error string
|
|
|
+ """
|
|
|
+ for iname, ivtype, ivalue, idesc in self.itemData.itervalues():
|
|
|
+ if iname == name:
|
|
|
+ return _("Variable <%s> already exists in the model. "
|
|
|
+ "Adding variable failed.") % name
|
|
|
+
|
|
|
+ index = self.InsertStringItem(sys.maxint, name)
|
|
|
+ self.SetStringItem(index, 0, name)
|
|
|
+ self.SetStringItem(index, 1, vtype)
|
|
|
+ self.SetStringItem(index, 2, value)
|
|
|
+ self.SetStringItem(index, 3, desc)
|
|
|
+ self.SetItemData(index, self.itemCount)
|
|
|
+
|
|
|
+ self.itemData[self.itemCount] = (name, vtype, value, desc)
|
|
|
+ self.itemCount += 1
|
|
|
+
|
|
|
+ return None
|
|
|
+
|
|
|
+ def OnRemove(self, event):
|
|
|
+ """!Remove selected variable(s) from the model"""
|
|
|
+ item = self.GetFirstSelected()
|
|
|
+ while item != -1:
|
|
|
+ self.DeleteItem(item)
|
|
|
+ del self.itemData[item]
|
|
|
+ item = self.GetFirstSelected()
|
|
|
+ event.Skip()
|
|
|
+
|
|
|
+ def OnRemoveAll(self, event):
|
|
|
+ """!Remove all variable(s) from the model"""
|
|
|
+ self.DeleteAllItems()
|
|
|
+ self.itemData = dict()
|
|
|
|
|
|
def main():
|
|
|
app = wx.PySimpleApp()
|