[GRASS-SVN] r72333 - grass/branches/releasebranch_7_4/gui/wxpython/gmodeler

svn_grass at osgeo.org svn_grass at osgeo.org
Fri Mar 9 03:26:53 PST 2018


Author: martinl
Date: 2018-03-09 03:26:53 -0800 (Fri, 09 Mar 2018)
New Revision: 72333

Modified:
   grass/branches/releasebranch_7_4/gui/wxpython/gmodeler/frame.py
   grass/branches/releasebranch_7_4/gui/wxpython/gmodeler/giface.py
   grass/branches/releasebranch_7_4/gui/wxpython/gmodeler/model.py
Log:
wxGUI/gmodeler: print command finished message
                print model computation finished message
                delete intermediate data when model finished
                implement display data functionality
                (merge r72300:72302,r72308,r72313:72314 from trunk)


Modified: grass/branches/releasebranch_7_4/gui/wxpython/gmodeler/frame.py
===================================================================
--- grass/branches/releasebranch_7_4/gui/wxpython/gmodeler/frame.py	2018-03-08 13:00:42 UTC (rev 72332)
+++ grass/branches/releasebranch_7_4/gui/wxpython/gmodeler/frame.py	2018-03-09 11:26:53 UTC (rev 72333)
@@ -11,7 +11,7 @@
  - frame::ItemPanel
  - frame::PythonPanel
 
-(C) 2010-2014 by the GRASS Development Team
+(C) 2010-2018 by the GRASS Development Team
 
 This program is free software under the GNU General Public License
 (>=v2). Read the file COPYING that comes with GRASS for details.
@@ -38,7 +38,8 @@
         import wx.lib.agw.flatnotebook as FN
 else:
     import wx.lib.flatnotebook as FN
-
+from wx.lib.newevent import NewEvent
+    
 from core.utils import _
 from gui_core.widgets import GNotebook
 from core.gconsole        import GConsole, \
@@ -61,6 +62,8 @@
 from gmodeler.model import *
 from gmodeler.dialogs import *
 
+wxModelDone, EVT_MODEL_DONE = NewEvent()
+
 from grass.script.utils import try_remove
 from grass.script import core as grass
 
@@ -148,7 +151,8 @@
         # rewrite default method to avoid hiding progress bar
         self._gconsole.Bind(EVT_CMD_DONE, self.OnCmdDone)
         self.Bind(EVT_CMD_PREPARE, self.OnCmdPrepare)
-
+        self.Bind(EVT_MODEL_DONE, self.OnModelDone)
+        
         self.notebook.AddPage(page=self.canvas, text=_('Model'), name='model')
         self.notebook.AddPage(
             page=self.itemPanel,
@@ -288,11 +292,37 @@
 
     def OnCmdDone(self, event):
         """Command done (or aborted)"""
-        self.goutput.GetProgressBar().SetValue(0)
+        def time_elapsed(etime):
+            try:
+                ctime = time.time() - etime
+                if ctime < 60:
+                    stime = _("%d sec") % int(ctime)
+                else:
+                    mtime = int(ctime / 60)
+                    stime = _("%(min)d min %(sec)d sec") % {
+                        'min': mtime, 'sec': int(ctime - (mtime * 60))}
+            except KeyError:
+                # stopped deamon
+                stime = _("unknown")
+
+            return stime
+        
+        self.goutput.GetProgressBar().SetValue(0)            
+        self.goutput.WriteCmdLog('({}) {} ({})'.format(
+            str(time.ctime()), _("Command finished"), time_elapsed(event.time)),
+            notification=event.notification)
+
         try:
             action = self.GetModel().GetItems()[event.pid]
             if hasattr(action, "task"):
                 action.Update(running=True)
+            if event.pid == self._gconsole.cmdThread.GetId() - 1:
+                self.goutput.WriteCmdLog('({}) {} ({})'.format(
+                    str(time.ctime()), _("Model computation finished"), time_elapsed(self.start_time)),
+                                         notification=event.notification)
+                event = wxModelDone()
+                wx.PostEvent(self, event)
+                
         except IndexError:
             pass
 
@@ -357,6 +387,22 @@
 
         dlg.Destroy()
 
+    def _deleteIntermediateData(self):
+        """Delete intermediate data"""
+        rast, vect, rast3d, msg = self.model.GetIntermediateData()
+        if rast:
+            self._gconsole.RunCmd(['g.remove', '-f', 'type=raster',
+                                   'name=%s' % ','.join(rast)])
+        if rast3d:
+            self._gconsole.RunCmd(['g.remove', '-f', 'type=raster_3d',
+                                   'name=%s' % ','.join(rast3d)])
+        if vect:
+            self._gconsole.RunCmd(['g.remove', '-f', 'type=vector',
+                                   'name=%s' % ','.join(vect)])
+                
+        self.SetStatusText(_("%d intermediate maps deleted from current mapset") %
+                           int(len(rast) + len(rast3d) + len(vect)))
+
     def OnDeleteData(self, event):
         """Delete intermediate data"""
         rast, vect, rast3d, msg = self.model.GetIntermediateData()
@@ -375,25 +421,10 @@
             style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
 
         ret = dlg.ShowModal()
+        dlg.Destroy()
         if ret == wx.ID_YES:
-            dlg.Destroy()
+            self._deleteIntermediateData()
 
-            if rast:
-                self._gconsole.RunCmd(['g.remove', '-f', 'type=raster',
-                                       'name=%s' % ','.join(rast)])
-            if rast3d:
-                self._gconsole.RunCmd(['g.remove', '-f', 'type=raster_3d',
-                                       'name=%s' % ','.join(rast3d)])
-            if vect:
-                self._gconsole.RunCmd(['g.remove', '-f', 'type=vector',
-                                       'name=%s' % ','.join(vect)])
-
-            self.SetStatusText(_("%d maps deleted from current mapset") %
-                               int(len(rast) + len(rast3d) + len(vect)))
-            return
-
-        dlg.Destroy()
-
     def OnModelNew(self, event):
         """Create new model"""
         Debug.msg(4, "ModelFrame.OnModelNew():")
@@ -580,15 +611,14 @@
 
     def OnRunModel(self, event):
         """Run entire model"""
-        self.model.Run(self._gconsole, self.OnDone, parent=self)
+        self.start_time = time.time()
+        self.model.Run(self._gconsole, self.OnModelDone, parent=self)
 
-    def OnDone(self, event):
+    def OnModelDone(self, event):
         """Computation finished
-
-        .. todo::
-            not called -- must be fixed
         """
         self.SetStatusText('', 0)
+        
         # restore original files
         if hasattr(self.model, "fileInput"):
             for finput in self.model.fileInput:
@@ -603,6 +633,25 @@
                     fd.close()
             del self.model.fileInput
 
+        # delete intermediate data
+        self._deleteIntermediateData()
+
+        # display data if required
+        for data in self.model.GetData():
+            if not data.HasDisplay():
+                continue
+
+            # remove existing map layers first
+            layers =  self._giface.GetLayerList().GetLayersByName(data.GetValue())
+            if layers:
+                for layer in layers:
+                    self._giface.GetLayerList().DeleteLayer(layer)
+                
+            # add new map layer
+            self._giface.GetLayerList().AddLayer(
+                ltype=data.GetPrompt(), name=data.GetValue(), checked=True,
+                cmd=data.GetDisplayCmd())
+
     def OnValidateModel(self, event, showMsg=True):
         """Validate entire model"""
         if self.model.GetNumItems() < 1:
@@ -1434,7 +1483,7 @@
         if not hasattr(self, "popupID"):
             self.popupID = dict()
             for key in ('remove', 'enable', 'addPoint',
-                        'delPoint', 'intermediate', 'props', 'id',
+                        'delPoint', 'intermediate', 'display', 'props', 'id',
                         'label', 'comment'):
                 self.popupID[key] = wx.NewId()
 
@@ -1496,20 +1545,38 @@
             if len(shape.GetLineControlPoints()) == 2:
                 popupMenu.Enable(self.popupID['delPoint'], False)
 
-        if isinstance(shape, ModelData) and '@' not in shape.GetValue():
+        if isinstance(shape, ModelData):
             popupMenu.AppendSeparator()
-            popupMenu.Append(
-                self.popupID['intermediate'],
-                text=_('Intermediate'),
-                kind=wx.ITEM_CHECK)
-            if self.GetShape().IsIntermediate():
-                popupMenu.Check(self.popupID['intermediate'], True)
+            if '@' not in shape.GetValue() and \
+               len(self.GetShape().GetRelations('from')) > 0:
+                popupMenu.Append(
+                    self.popupID['intermediate'],
+                    text=_('Intermediate'),
+                    kind=wx.ITEM_CHECK)
+                if self.GetShape().IsIntermediate():
+                    popupMenu.Check(self.popupID['intermediate'], True)
 
-            self.frame.Bind(
-                wx.EVT_MENU,
-                self.OnIntermediate,
-                id=self.popupID['intermediate'])
+                self.frame.Bind(
+                    wx.EVT_MENU,
+                    self.OnIntermediate,
+                    id=self.popupID['intermediate'])
 
+            if self.frame._giface.GetMapDisplay():
+                popupMenu.Append(
+                    self.popupID['display'],
+                    text=_('Display'),
+                    kind=wx.ITEM_CHECK)
+                if self.GetShape().HasDisplay():
+                    popupMenu.Check(self.popupID['display'], True)
+
+                self.frame.Bind(
+                    wx.EVT_MENU,
+                    self.OnHasDisplay,
+                    id=self.popupID['display'])
+
+                if self.GetShape().IsIntermediate():
+                    popupMenu.Enable(self.popupID['display'], False)
+
         if isinstance(shape, ModelData) or \
                 isinstance(shape, ModelAction) or \
                 isinstance(shape, ModelLoop):
@@ -1614,6 +1681,29 @@
         shape.SetIntermediate(event.IsChecked())
         self.frame.canvas.Refresh()
 
+    def OnHasDisplay(self, event):
+        """Mark data to be displayed"""
+        self.frame.ModelChanged()
+        shape = self.GetShape()
+        shape.SetHasDisplay(event.IsChecked())
+        self.frame.canvas.Refresh()
+
+        try:
+            if event.IsChecked():
+                # add map layer to display
+                self.frame._giface.GetLayerList().AddLayer(
+                    ltype=shape.GetPrompt(), name=shape.GetValue(), checked=True,
+                    cmd=shape.GetDisplayCmd())
+            else:
+                # remove map layer(s) from display
+                layers = self.frame._giface.GetLayerList().GetLayersByName(shape.GetValue())
+                for layer in layers:
+                    self.frame._giface.GetLayerList().DeleteLayer(layer)
+                    
+        except GException as e:
+            GError(parent=self,
+                   message='{}'.format(e))
+
     def OnRemove(self, event):
         """Remove shape
         """

Modified: grass/branches/releasebranch_7_4/gui/wxpython/gmodeler/giface.py
===================================================================
--- grass/branches/releasebranch_7_4/gui/wxpython/gmodeler/giface.py	2018-03-08 13:00:42 UTC (rev 72332)
+++ grass/branches/releasebranch_7_4/gui/wxpython/gmodeler/giface.py	2018-03-09 11:26:53 UTC (rev 72333)
@@ -6,7 +6,7 @@
 Classes:
  - giface::GraphicalModelerGrassInterface
 
-(C) 2013-2014 by the GRASS Development Team
+(C) 2013-2018 by the GRASS Development Team
 
 This program is free software under the GNU General Public License
 (>=v2). Read the file COPYING that comes with GRASS for details.

Modified: grass/branches/releasebranch_7_4/gui/wxpython/gmodeler/model.py
===================================================================
--- grass/branches/releasebranch_7_4/gui/wxpython/gmodeler/model.py	2018-03-08 13:00:42 UTC (rev 72332)
+++ grass/branches/releasebranch_7_4/gui/wxpython/gmodeler/model.py	2018-03-09 11:26:53 UTC (rev 72333)
@@ -18,7 +18,7 @@
  - model::WritePythonFile
  - model::ModelParamDialog
 
-(C) 2010-2016 by the GRASS Development Team
+(C) 2010-2018 by the GRASS Development Team
 
 This program is free software under the GNU General Public License
 (>=v2). Read the file COPYING that comes with GRASS for details.
@@ -354,6 +354,7 @@
                                  prompt=data['prompt'],
                                  value=data['value'])
             dataItem.SetIntermediate(data['intermediate'])
+            dataItem.SetHasDisplay(data['display'])
 
             for rel in data['rels']:
                 actionItem = self.FindAction(rel['id'])
@@ -569,7 +570,7 @@
     def OnPrepare(self, item, params):
         self._substituteFile(item, params, checkOnly=False)
 
-    def RunAction(self, item, params, log, onDone,
+    def RunAction(self, item, params, log, onDone=None,
                   onPrepare=None, statusbar=None):
         """Run given action
 
@@ -683,7 +684,7 @@
             if isinstance(item, ModelAction):
                 if item.GetBlockId():
                     continue
-                self.RunAction(item, params, log, onDone)
+                self.RunAction(item, params, log)
             elif isinstance(item, ModelLoop):
                 cond = item.GetLabel()
 
@@ -743,7 +744,7 @@
                         varDict['value'] = var
 
                         self.RunAction(item=action, params=params,
-                                       log=log, onDone=onDone)
+                                       log=log)
                 params['variables']['params'].remove(varDict)
 
         if delInterData:
@@ -1346,6 +1347,7 @@
         self.value = value
         self.prompt = prompt
         self.intermediate = False
+        self.display = False
         self.propWin = None
         if not width:
             width = UserSettings.Get(
@@ -1374,6 +1376,14 @@
         """Set intermediate flag"""
         self.intermediate = im
 
+    def HasDisplay(self):
+        """Checks if data item is marked to be displayed"""
+        return self.display
+
+    def SetHasDisplay(self, tbd):
+        """Set to-be-displayed flag"""
+        self.display = tbd
+
     def OnDraw(self, dc):
         self._setPen()
 
@@ -1506,7 +1516,21 @@
         self._setPen()
         self.SetLabel()
 
+    def GetDisplayCmd(self):
+        """Get display command as list"""
+        cmd = []
+        if self.prompt == 'raster':
+            cmd.append('d.rast')
+        elif self.prompt == 'vector':
+            cmd.append('d.vect')
+        else:
+            raise GException("Unsupported display prompt: {}".format(
+                self.prompt))
 
+        cmd.append('map=' + self.value)
+
+        return cmd
+
 class ModelRelation(ogl.LineShape):
     """Data - action relation"""
 
@@ -2018,11 +2042,10 @@
                 prompt = param.get('prompt', None)
                 value = self._filterValue(self._getNodeText(param, 'value'))
 
-            if data.find('intermediate') is None:
-                intermediate = False
-            else:
-                intermediate = True
+            intermediate = False if data.find('intermediate') is None else True
 
+            display = False if data.find('display') is None else True
+            
             rels = list()
             for rel in data.findall('relation'):
                 defrel = {'id': int(rel.get('id', -1)),
@@ -2041,6 +2064,7 @@
                               'prompt': prompt,
                               'value': value,
                               'intermediate': intermediate,
+                              'display': display,
                               'rels': rels})
 
     def _processTask(self, node):
@@ -2381,6 +2405,8 @@
 
             if data.IsIntermediate():
                 self.fd.write('%s<intermediate />\n' % (' ' * self.indent))
+            if data.HasDisplay():
+                self.fd.write('%s<display />\n' % (' ' * self.indent))
 
             # relations
             for ft in ('from', 'to'):



More information about the grass-commit mailing list