浏览代码

wxGUI/modeler: load model file (gxm)

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@41607 15284696-431f-4ddb-bdfa-cd5b030d7da7
Martin Landa 15 年之前
父节点
当前提交
5ed577f076
共有 1 个文件被更改,包括 161 次插入2 次删除
  1. 161 2
      gui/wxpython/gui_modules/gmodeler.py

+ 161 - 2
gui/wxpython/gui_modules/gmodeler.py

@@ -9,6 +9,8 @@ Classes:
  - ModelAction
  - ModelAction
  - ModelSearchDialog
  - ModelSearchDialog
  - ModelData
  - ModelData
+ - ProcessModelFile
+ - WriteModelFile
 
 
 (C) 2010 by the GRASS Development Team
 (C) 2010 by the GRASS Development Team
 This program is free software under the GNU General Public License
 This program is free software under the GNU General Public License
@@ -21,6 +23,11 @@ import os
 import shlex
 import shlex
 import time
 import time
 
 
+try:
+    import xml.etree.ElementTree as etree
+except ImportError:
+    import elementtree.ElementTree as etree # Python <= 2.4
+
 import globalvar
 import globalvar
 if not os.getenv("GRASS_WXBUNDLED"):
 if not os.getenv("GRASS_WXBUNDLED"):
     globalvar.CheckForWx()
     globalvar.CheckForWx()
@@ -32,6 +39,9 @@ import menudata
 import toolbars
 import toolbars
 import menuform
 import menuform
 import prompt
 import prompt
+import gcmd
+import utils
+from   debug import Debug
 
 
 from grass.script import core as grass
 from grass.script import core as grass
 
 
@@ -49,6 +59,8 @@ class ModelFrame(wx.Frame):
         self.searchDialog = None # module search dialog
         self.searchDialog = None # module search dialog
         self.actions = list()    # list of recorded actions
         self.actions = list()    # list of recorded actions
         self.data    = list()    # list of recorded data items
         self.data    = list()    # list of recorded data items
+        self.baseTitle = title
+        self.modelFile = None    # loaded model
         
         
         wx.Frame.__init__(self, parent = parent, id = id, title = title, **kwargs)
         wx.Frame.__init__(self, parent = parent, id = id, title = title, **kwargs)
         self.SetName("Modeler")
         self.SetName("Modeler")
@@ -102,8 +114,31 @@ class ModelFrame(wx.Frame):
 
 
     def OnModelOpen(self, event):
     def OnModelOpen(self, event):
         """!Load model from file"""
         """!Load model from file"""
-        pass
-
+        debug = True
+        if debug is False:
+            dlg = wx.FileDialog(parent = self, message=_("Choose model file"),
+                                defaultDir = os.getcwd(),
+                                wildcard=_("GRASS Model File (*.gxm)|*.gxm"))
+            if dlg.ShowModal() == wx.ID_OK:
+                filename = dlg.GetPath()
+        
+        else:
+            filename = '/home/martin/model.gxm'
+            
+        if not filename:
+            return
+        
+        Debug.msg(4, "ModelFrame.OnModelOpen(): filename=%s" % filename)
+        
+        # close current model
+        ### self.OnModelClose()
+        
+        self.LoadModelFile(filename)
+        
+        self.modelFile = filename
+        self.SetTitle(self.baseTitle + " - " +  os.path.basename(self.modelFile))
+        self.SetStatusText(_('%d actions loaded into model') % len(self.actions), 0)
+        
     def OnModelSave(self, event):
     def OnModelSave(self, event):
         """!Save model to file"""
         """!Save model to file"""
         pass
         pass
@@ -223,6 +258,43 @@ class ModelFrame(wx.Frame):
             self.canvas.Refresh()
             self.canvas.Refresh()
         
         
         self.SetStatusText(layer.GetLog(), 0)
         self.SetStatusText(layer.GetLog(), 0)
+
+    def LoadModelFile(self, filename):
+        """!Load model definition stored in GRASS Model XML file (gxm)
+
+        @todo Validate against DTD
+
+        Raise exception on error.
+        """
+        ### dtdFilename = os.path.join(globalvar.ETCWXDIR, "xml", "grass-gxm.dtd")
+        
+        # parse workspace file
+        try:
+            gxmXml = ProcessModelFile(etree.parse(filename))
+        except Exception, err:
+            raise gcmd.GStdError(_("Reading model file <%(file)s> failed.\n"
+                                   "Invalid file, unable to parse XML document."
+                                   "\n\n%(err)s") % { 'file' : filename, 'err': err},
+                                 parent = self)
+        
+        busy = wx.BusyInfo(message=_("Please wait, loading model..."),
+                           parent=self)
+        wx.Yield()
+        # load model
+        for action in gxmXml.actions:
+            actionShape = ModelAction(parent = self, 
+                                      x = action['pos'][0],
+                                      y = action['pos'][1],
+                                      width = action['size'][0],
+                                      height = action['size'][1],
+                                      cmd = action['cmd'])
+            self.canvas.diagram.AddShape(actionShape)
+            actionShape.Show(True)
+            
+            self._addEvent(actionShape)
+            self.actions.append(actionShape)
+        
+        self.canvas.Refresh(True)
         
         
 class ModelCanvas(ogl.ShapeCanvas):
 class ModelCanvas(ogl.ShapeCanvas):
     """!Canvas where model is drawn"""
     """!Canvas where model is drawn"""
@@ -448,7 +520,94 @@ class ModelSearchDialog(wx.Dialog):
         self.searchBy.SetSelection(0)
         self.searchBy.SetSelection(0)
         self.search.SetValue('')
         self.search.SetValue('')
         self.cmd_prompt.OnCmdErase(None)
         self.cmd_prompt.OnCmdErase(None)
+
+class ProcessModelFile:
+    """!Process GRASS model file (gxm)"""
+    def __init__(self, tree):
+        """!A ElementTree handler for the GXM XML file, as defined in
+        grass-gxm.dtd.
+        """
+        self.tree = tree
+        self.root = self.tree.getroot()
+
+        # list of actions, data
+        self.actions = list()
+        
+        self._processFile()
+
+    def _filterValue(self, value):
+        """!Filter value
+        
+        @param value
+        """
+        value = value.replace('&lt;', '<')
+        value = value.replace('&gt;', '>')
+        
+        return value
+        
+    def _getNodeText(self, node, tag, default = ''):
+        """!Get node text"""
+        p = node.find(tag)
+        if p is not None:
+            return utils.normalize_whitespace(p.text)
         
         
+        return default
+    
+    def _processFile(self):
+        """!Process model file"""
+        for action in self.root.findall('action'):
+            pos = size = None
+            posAttr = action.get('position', None)
+            if posAttr:
+                posVal = map(int, posAttr.split(','))
+                try:
+                    pos = (posVal[0], posVal[1])
+                except:
+                    pos = None
+
+            sizeAttr = action.get('size', None)
+            if sizeAttr:
+                sizeVal = map(int, sizeAttr.split(','))
+                try:
+                    size = (sizeVal[0], sizeVal[1])
+                except:
+                    size = None
+                    
+            task = action.find('task')
+            if task:
+                cmd = self._processTask(task)
+            else:
+                cmd = None
+            
+            self.actions.append({ 'pos' : pos,
+                                  'size': size,
+                                  'cmd' : cmd })
+            
+    def _processTask(self, node):
+        """!Process task"""
+        cmd = list()
+        name = node.get('name', None)
+        if not name:
+            return cmd
+        cmd.append(name)
+        
+        # flags
+        for p in node.findall('flag'):
+            flag = p.get('name', '')
+            if len(flag) > 1:
+                cmd.append('--' + flag)
+            else:
+                cmd.append('-' + flag)
+        # parameters
+        for p in node.findall('parameter'):
+            cmd.append('%s=%s' % (p.get('name', ''),
+                                  self._filterValue(self._getNodeText(p, 'value'))))
+        return cmd
+    
+class WriteModelFile:
+    """!Write GRASS model file (gxm)"""
+    pass
+
 def main():
 def main():
     app = wx.PySimpleApp()
     app = wx.PySimpleApp()
     frame = ModelFrame(parent = None)
     frame = ModelFrame(parent = None)