[GRASS-SVN] r65158 - in grass/trunk/gui/wxpython: core mapdisp
svn_grass at osgeo.org
svn_grass at osgeo.org
Mon Apr 27 12:06:29 PDT 2015
Author: martinl
Date: 2015-04-27 12:06:29 -0700 (Mon, 27 Apr 2015)
New Revision: 65158
Modified:
grass/trunk/gui/wxpython/core/render.py
grass/trunk/gui/wxpython/core/utils.py
grass/trunk/gui/wxpython/mapdisp/main.py
Log:
wxGUI: modify standalone wx0 monitors to render map layers into
mapfile to void g.pnmcomp call (work in progress) see also #2286
Modified: grass/trunk/gui/wxpython/core/render.py
===================================================================
--- grass/trunk/gui/wxpython/core/render.py 2015-04-27 19:04:19 UTC (rev 65157)
+++ grass/trunk/gui/wxpython/core/render.py 2015-04-27 19:06:29 UTC (rev 65158)
@@ -17,7 +17,7 @@
- render::Overlay
- render::Map
-(C) 2006-2014 by the GRASS Development Team
+(C) 2006-2015 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.
@@ -50,10 +50,6 @@
from core.debug import Debug
from core.settings import UserSettings
-
-USE_GPNMCOMP = True
-
-
class Layer(object):
"""Virtual class which stores information about layers (map layers and
overlays) of the map composition.
@@ -62,7 +58,7 @@
- For overlays use Overlay class.
"""
def __init__(self, ltype, cmd, Map, name=None,
- active=True, hidden=False, opacity=1.0):
+ active=True, hidden=False, opacity=1.0, mapfile=None):
"""Create new instance
.. todo::
@@ -77,10 +73,11 @@
:param active: layer is active, will be rendered only if True
:param hidden: layer is hidden, won't be listed in Layer Manager if True
:param float opacity: layer opacity <0;1>
+ :param mapfile full path to output file or None
"""
-
- # generated file for each layer
- if USE_GPNMCOMP or ltype == 'overlay':
+ if mapfile:
+ self.mapfile = mapfile
+ else:
if ltype == 'overlay':
tempfile_sfx = ".png"
else:
@@ -90,10 +87,8 @@
# we don't want it open, we just need the name
self.mapfile = mapfile.name
mapfile.close()
- self.maskfile = self.mapfile.rsplit(".",1)[0] + ".pgm"
- else:
- self.mapfile = self.maskfile = None
-
+ self.maskfile = self.mapfile.rsplit(".",1)[0] + ".pgm"
+
# stores class which manages rendering instead of simple command - e.g. WMS
self.renderMgr = None
@@ -101,7 +96,6 @@
self.type = None
self.SetType(ltype)
self.name = name
- self.environ = os.environ.copy()
if self.type == 'command':
self.cmd = list()
@@ -116,6 +110,8 @@
self.forceRender = True
+ self.render_env = { "GRASS_RENDER_FILE": self.mapfile }
+
Debug.msg (3, "Layer.__init__(): type=%s, cmd='%s', name=%s, " \
"active=%d, opacity=%d, hidden=%d" % \
(self.type, self.GetCmd(string=True), self.name,
@@ -125,7 +121,13 @@
Debug.msg (3, "Layer.__del__(): layer=%s, cmd='%s'" %
(self.name, self.GetCmd(string = True)))
- def Render(self):
+ def __str__(self):
+ return self.name
+
+ def __repr__(self):
+ return self.__str__()
+
+ def Render(self, env):
"""Render layer to image
:return: rendered image filename
@@ -138,8 +140,8 @@
if self.type == '3d-raster':
return None
- Debug.msg (3, "Layer.Render(): type=%s, name=%s" % \
- (self.type, self.name))
+ Debug.msg (3, "Layer.Render(): type=%s, name=%s, file=%s" % \
+ (self.type, self.name, self.mapfile))
# prepare command for each layer
layertypes = utils.command2ltype.values() + ['overlay', 'command']
@@ -148,23 +150,21 @@
raise GException(_("<%(name)s>: layer type <%(type)s> is not supported") % \
{'type' : self.type, 'name' : self.name})
- if self.mapfile:
- self.environ["GRASS_RENDER_FILE"] = self.mapfile
-
+ env.update(self.render_env)
# execute command
try:
if self.type == 'command':
read = False
for c in self.cmd:
- ret, msg = self._runCommand(c)
+ ret, msg = self._runCommand(c, env)
if ret != 0:
break
if not read:
- self.environ["GRASS_RENDER_FILE_READ"] = "TRUE"
+ env["GRASS_RENDER_FILE_READ"] = "TRUE"
- self.environ["GRASS_RENDER_FILE_READ"] = "FALSE"
+ env["GRASS_RENDER_FILE_READ"] = "FALSE"
else:
- ret, msg = self._runCommand(self.cmd)
+ ret, msg = self._runCommand(self.cmd, env)
if ret != 0:
sys.stderr.write(_("Command '%s' failed\n") % self.GetCmd(string = True))
if msg:
@@ -183,18 +183,18 @@
return self.mapfile
- def _runCommand(self, cmd):
+ def _runCommand(self, cmd, env):
"""Run command to render data
"""
if self.type == 'wms':
ret = 0
msg = ''
- self.renderMgr.Render(cmd, env=self.environ)
+ self.renderMgr.Render(cmd, env=env)
else:
ret, msg = RunCommand(cmd[0],
getErrorMsg = True,
quiet = True,
- env=self.environ,
+ env=env,
**cmd[1])
return ret, msg
@@ -318,10 +318,6 @@
# for re-rendering
self.forceRender = True
- def SetEnvironment(self, environ):
- """Sets environment for rendering."""
- self.environ = environ
-
def IsDownloading(self):
"""Is data downloading from web server e. g. wms"""
if self.renderMgr is None:
@@ -341,23 +337,11 @@
return self.renderMgr
class MapLayer(Layer):
- def __init__(self, ltype, cmd, Map, name = None,
- active = True, hidden = False, opacity = 1.0):
+ def __init__(self, *args, **kwargs):
"""Represents map layer in the map canvas
-
- :param ltype: layer type ('raster', 'vector', 'command', etc.)
- :param cmd: GRASS command to render layer,
- given as list, e.g. ['d.rast',
- 'map=elevation at PERMANENT']
- :param map: render.Map instance
- :param name: layer name, e.g. 'elevation at PERMANENT' (for layer tree) or None
- :param active: layer is active, will be rendered only if True
- :param hidden: layer is hidden, won't be listed in Layer Manager if True
- :param opacity: layer opacity <0;1>
"""
- Layer.__init__(self, ltype, cmd, Map, name,
- active, hidden, opacity)
-
+ Layer.__init__(self, *args, **kwargs)
+
def GetMapset(self):
"""Get mapset of map layer
@@ -373,24 +357,16 @@
return self.name
class Overlay(Layer):
- def __init__(self, id, ltype, cmd, Map,
- active = True, hidden = True, opacity = 1.0):
+ def __init__(self, id, *args, **kwargs):
"""Represents overlay displayed in map canvas
:param id: overlay id (for PseudoDC)
- :param type: overlay type ('barscale', 'legend', etc.)
- :param cmd: GRASS command to render overlay,
- given as list, e.g. ['d.legend',
- 'raster=elevation at PERMANENT']
- :param map: render.Map instance
- :param active: layer is active, will be rendered only if True
- :param hidden: layer is hidden, won't be listed in Layer Manager if True
- :param opacity: layer opacity <0;1>
"""
- Layer.__init__(self, 'overlay', cmd, Map, ltype,
- active, hidden, opacity)
+ Layer.__init__(self, ltype='overlay', *args, **kwargs)
self.id = id
-
+ self.render_env["GRASS_RENDER_FILE_READ"] = "FALSE"
+ self.render_env["GRASS_RENDER_TRANSPARENT"] = "TRUE"
+
class Map(object):
def __init__(self, gisrc = None):
"""Map composition (stack of map layers and overlays)
@@ -415,7 +391,7 @@
# generated file for g.pnmcomp output for rendering the map
self.mapfile = grass.tempfile(create = False) + '.ppm'
-
+
# setting some initial env. variables
if not self.GetWindow():
sys.stderr.write(_("Trying to recover from default region..."))
@@ -425,10 +401,10 @@
self.progressInfo = None
# GRASS environment variable (for rendering)
- self.default_env = {"GRASS_RENDER_BACKGROUNDCOLOR" : "000000",
+ self.render_env = {"GRASS_RENDER_BACKGROUNDCOLOR" : "000000",
"GRASS_RENDER_FILE_COMPRESSION" : "0",
"GRASS_RENDER_TRUECOLOR" : "TRUE",
- "GRASS_RENDER_TRANSPARENT" : "TRUE"
+ "GRASS_RENDER_TRANSPARENT" : "TRUE",
}
# projection info
@@ -864,7 +840,7 @@
else:
selected.append(layer)
- Debug.msg (3, "Map.GetListOfLayers(): numberof=%d" % len(selected))
+ Debug.msg (3, "Map.GetListOfLayers(ltype=%s): -> %d" % (ltype, len(selected)))
return selected
@@ -886,10 +862,9 @@
layers = self.layers + self.overlays
self.downloading = False
-
+
self.ReportProgress(layer=None)
-
for layer in layers:
# skip non-active map layers
if not layer or not layer.active:
@@ -897,8 +872,7 @@
# render
if force or layer.forceRender:
- layer.SetEnvironment(env)
- if not layer.Render():
+ if not layer.Render(env):
continue
if layer.IsDownloading():
@@ -915,9 +889,7 @@
maps.append(layer.mapfile)
masks.append(layer.maskfile)
opacities.append(str(layer.opacity))
-
- Debug.msg(3, "Map.Render() type=%s, layer=%s " % (layer.type, layer.name))
-
+
return maps, masks, opacities
def GetMapsMasksAndOpacities(self, force, windres, env):
@@ -942,7 +914,7 @@
"""
wx.BeginBusyCursor()
env = os.environ.copy()
- env.update(self.default_env)
+ env.update(self.render_env)
# use external gisrc if defined
if self.gisrc:
env['GISRC'] = self.gisrc
@@ -1004,6 +976,24 @@
return self.mapfile
+ def _addLayer(self, layer, render=False, pos=-1):
+ if layer.type == 'overlay':
+ llist = self.overlays
+ else:
+ llist = self.layers
+
+ # add maplayer to the list of layers
+ if pos > -1:
+ llist.insert(pos, layer)
+ else:
+ llist.append(layer)
+
+ Debug.msg (3, "Map._addLayer(): layer=%s type=%s" % (layer.name, layer.type))
+ if render and not layer.Render():
+ raise GException(_("Unable to render map layer <%s>.") % name)
+
+ return layer
+
def AddLayer(self, ltype, command, name = None,
active = True, hidden = False, opacity = 1.0, render = False,
pos = -1):
@@ -1021,7 +1011,6 @@
:return: new layer on success
:return: None on failure
"""
- wx.BeginBusyCursor()
# opacity must be <0;1>
if opacity < 0:
opacity = 0
@@ -1029,27 +1018,16 @@
opacity = 1
layer = MapLayer(ltype = ltype, name = name, cmd = command, Map = self,
active = active, hidden = hidden, opacity = opacity)
-
- # add maplayer to the list of layers
- if pos > -1:
- self.layers.insert(pos, layer)
- else:
- self.layers.append(layer)
-
- Debug.msg (3, "Map.AddLayer(): layer=%s" % layer.name)
- if render:
- if not layer.Render():
- raise GException(_("Unable to render map layer <%s>.") % name)
-
+
+ self._addLayer(layer, render, pos)
+
renderMgr = layer.GetRenderMgr()
if renderMgr:
renderMgr.dataFetched.connect(self.layerChanged)
renderMgr.updateProgress.connect(self.ReportProgress)
-
- wx.EndBusyCursor()
-
+
self.layerAdded.emit(layer=layer)
-
+
return layer
def DeleteAllLayers(self, overlay = False):
@@ -1095,15 +1073,8 @@
def SetLayers(self, layers):
self.layers = layers
+ Debug.msg(5, "Map.SetLayers(): layers=%s" % (layers))
- # only for debug
- # might be removed including message, it seems more than clear
- layerNameList = ""
- for layer in self.layers:
- if layer.GetName():
- layerNameList += layer.GetName() + ','
- Debug.msg(5, "Map.SetLayers(): layers=%s" % (layerNameList))
-
def ChangeLayer(self, layer, render = False, **kargs):
"""Change map layer properties
@@ -1242,18 +1213,11 @@
:return: None on failure
"""
Debug.msg (2, "Map.AddOverlay(): cmd=%s, render=%d" % (command, render))
- overlay = Overlay(id = id, ltype = ltype, cmd = command, Map = self,
+ overlay = Overlay(id = id, name = ltype, cmd = command, Map = self,
active = active, hidden = hidden, opacity = opacity)
+
+ return self._addLayer(overlay, render)
- # add maplayer to the list of layers
- self.overlays.append(overlay)
-
- if render and command != '' and not overlay.Render():
- raise GException(_("Unable to render overlay <%s>.") %
- ltype)
-
- return self.overlays[-1]
-
def ChangeOverlay(self, id, render = False, **kargs):
"""Change overlay properities
Modified: grass/trunk/gui/wxpython/core/utils.py
===================================================================
--- grass/trunk/gui/wxpython/core/utils.py 2015-04-27 19:04:19 UTC (rev 65157)
+++ grass/trunk/gui/wxpython/core/utils.py 2015-04-27 19:06:29 UTC (rev 65158)
@@ -971,7 +971,8 @@
'd.graph' : 'graph',
'd.out.file' : 'export',
'd.to.rast' : 'torast',
- 'd.text' : 'text'
+ 'd.text' : 'text',
+ 'd.northarrow' : 'northarrow'
}
ltype2command = {}
for (cmd, ltype) in command2ltype.items():
Modified: grass/trunk/gui/wxpython/mapdisp/main.py
===================================================================
--- grass/trunk/gui/wxpython/mapdisp/main.py 2015-04-27 19:04:19 UTC (rev 65157)
+++ grass/trunk/gui/wxpython/mapdisp/main.py 2015-04-27 19:06:29 UTC (rev 65158)
@@ -5,6 +5,7 @@
Classes:
- mapdisp::DMonMap
+ - mapdisp::DMonMapDirect
- mapdisp::Layer
- mapdisp::LayerList
- mapdisp::DMonGrassInterface
@@ -14,7 +15,7 @@
Usage:
python mapdisp/main.py monitor-identifier /path/to/map/file /path/to/command/file /path/to/env/file
-(C) 2006-2014 by the GRASS Development Team
+(C) 2006-2015 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.
@@ -37,7 +38,7 @@
from core import utils
from core.giface import StandaloneGrassInterface
from core.gcmd import RunCommand
-from core.render import Map, MapLayer
+from core.render import Map, MapLayer, Overlay
from core.utils import _
from mapdisp.frame import MapFrame
from core.debug import Debug
@@ -64,7 +65,6 @@
:param cmdline: full path to the cmd file (defined by d.mon)
:param mapfile: full path to the map file (defined by d.mon)
"""
-
Map.__init__(self)
self._giface = giface
@@ -93,21 +93,21 @@
# signal sent when d.what.rast/vect appears in cmd file, attribute is cmd
self.query = Signal('DMonMap.query')
- def GetLayersFromCmdFile(self):
+ def GetLayersFromCmdFile(self, mapfile=None):
"""Get list of map layers from cmdfile
"""
if not self.cmdfile:
return
nlayers = 0
-
try:
fd = open(self.cmdfile, 'r')
lines = fd.readlines()
fd.close()
# detect d.out.file, delete the line from the cmd file and export graphics
if len(lines) > 0:
- if lines[-1].startswith('d.out.file') or lines[-1].startswith('d.to.rast'):
+ if lines[-1].startswith('d.out.file') or \
+ lines[-1].startswith('d.to.rast'):
dCmd = lines[-1].strip()
fd = open(self.cmdfile, 'w')
fd.writelines(lines[:-1])
@@ -128,38 +128,42 @@
maps = utils.split(dWhatCmd)[1].split(',')
self.query.emit(ltype=utils.split(dWhatCmd)[0].split('.')[-1], maps=maps)
return
-
+
existingLayers = self.GetListOfLayers()
# holds new rendreing order for every layer in existingLayers
- layersOrder = [-1] * len(self.GetListOfLayers())
+ layersOrder = [-1] * len(existingLayers)
# next number in rendering order
next_layer = 0
-
for line in lines:
cmd = utils.split(line.strip())
+
ltype = None
-
try:
ltype = utils.command2ltype[cmd[0]]
except KeyError:
grass.warning(_("Unsupported command %s.") % cmd[0])
continue
-
+
name = utils.GetLayerNameFromCmd(cmd, fullyQualified = True,
layerType = ltype)[0]
- # creating temporary layer object to compare commands
- # neccessary to get the same format
- # supposing that there are no side effects
- tmpMapLayer = MapLayer(ltype = ltype, name = name,
- cmd = cmd, Map = None,
- active = False, hidden = True,
- opacity = 0)
+ args = {}
+ if ltype in ('barscale', 'legend', 'northarrow'):
+ classLayer = Overlay
+ args['id'] = 1
+ else:
+ classLayer = MapLayer
+ args['mapfile'] = mapfile
+ args['ltype'] = ltype
+
+ mapLayer = classLayer(name = name, cmd = cmd, Map = None,
+ hidden = True, **args)
+
exists = False
for i, layer in enumerate(existingLayers):
- if layer.GetCmd(string=True) == tmpMapLayer.GetCmd(string=True):
+ if layer.GetCmd(string=True) == mapLayer.GetCmd(string=True):
exists = True
if layersOrder[i] == -1:
@@ -176,12 +180,12 @@
break
if exists:
continue
-
- newLayer = Map.AddLayer(self, ltype = ltype, command = cmd, active = True, name = name)
+ newLayer = self._addLayer(mapLayer)
+
existingLayers.append(newLayer)
self.ownedLayers.append(newLayer)
-
+
layersOrder.append(next_layer)
next_layer += 1
@@ -202,27 +206,25 @@
# owned layer found in cmd file is added into proper rendering position
else:
reorderedLayers[layersOrder[i]] = layer
-
+
self.SetLayers(reorderedLayers)
-
+
except IOError as e:
grass.warning(_("Unable to read cmdfile '%(cmd)s'. Details: %(det)s") % \
{ 'cmd' : self.cmdfile, 'det' : e })
return
-
+
+ Debug.msg(1, "Map.GetLayersFromCmdFile(): cmdfile=%s, nlayers=%d" % \
+ (self.cmdfile, nlayers))
+
self._giface.updateMap.emit()
-
- Debug.msg(1, "Map.GetLayersFromCmdFile(): cmdfile=%s" % self.cmdfile)
- Debug.msg(1, " nlayers=%d" % nlayers)
-
+
def Render(self, *args, **kwargs):
"""Render layer to image.
For input params and returned data see overridden method in Map class.
"""
- ret = Map.Render(self, *args, **kwargs)
-
- return ret
+ return Map.Render(self, *args, **kwargs)
def AddLayer(self, *args, **kwargs):
"""Adds generic map layer to list of layers.
@@ -236,13 +238,57 @@
else:
os.environ["GRASS_RENDER_IMMEDIATE"] = "cairo"
- layer = Map.AddLayer(self, *args, **kwargs)
-
+ layer = Map.AddLayer(self, render = False, *args, **kwargs)
+ llayer.SetMapFile(self.mapfile)
+
del os.environ["GRASS_RENDER_IMMEDIATE"]
- return layer
+ #return layer
+class DMonMapDirect(DMonMap):
+ def __init__(self, giface, cmdfile=None, mapfile=None):
+ """Map composition (stack of map layers and overlays)
+ :param cmdline: full path to the cmd file (defined by d.mon)
+ :param mapfile: full path to the map file (defined by d.mon)
+ """
+ DMonMap.__init__(self, giface, cmdfile, mapfile)
+
+ self.render_env['GRASS_RENDER_BACKGROUNDCOLOR'] = 'FFFFFF'
+ self.render_env['GRASS_RENDER_TRANSPARENT'] = 'FALSE'
+ self.render_env['GRASS_RENDER_FILE_READ'] = 'TRUE'
+
+ def Render(self, *args, **kwargs):
+ """Render layer to image.
+
+ For input params and returned data see overridden method in Map class.
+ """
+ wx.BeginBusyCursor()
+ env = os.environ.copy()
+ env.update(self.render_env)
+ # use external gisrc if defined
+ if self.gisrc:
+ env['GISRC'] = self.gisrc
+ env['GRASS_REGION'] = self.SetRegion(kwargs.get('windres', False))
+ env['GRASS_RENDER_WIDTH'] = str(self.width)
+ env['GRASS_RENDER_HEIGHT'] = str(self.height)
+ driver = UserSettings.Get(group = 'display', key = 'driver', subkey = 'type')
+ if driver == 'png':
+ env['GRASS_RENDER_IMMEDIATE'] = 'png'
+ else:
+ env['GRASS_RENDER_IMMEDIATE'] = 'cairo'
+
+ if os.path.exists(self.mapfile):
+ os.remove(self.mapfile)
+
+ self.GetMapsMasksAndOpacities(kwargs['force'], kwargs.get('windres', False), env)
+ wx.EndBusyCursor()
+
+ return self.mapfile
+
+ def GetLayersFromCmdFile(self):
+ super(self.__class__, self).GetLayersFromCmdFile(self.mapfile)
+
class Layer(object):
"""@implements core::giface::Layer"""
def __init__(self, maplayer):
@@ -264,8 +310,8 @@
class LayerList(object):
+ """@implements core::giface::LayerList"""
def __init__(self, map, giface):
- """@implements core::giface::LayerList"""
self._map = map
self._giface = giface
@@ -389,10 +435,20 @@
# actual use of StandaloneGrassInterface not yet tested
# needed for adding functionality in future
self._giface = DMonGrassInterface(None)
+
+ return True
+
+ def CreateMapFrame(self, name, decorations=True):
+ toolbars = []
+ if decorations:
+ toolbars.append('map')
if __name__ == "__main__":
+ dmonMap = DMonMapDirect
+ # if decorations:
+ # dmonMap = DMonMap
self.cmdTimeStamp = os.path.getmtime(monFile['cmd'])
- self.Map = DMonMap(giface=self._giface, cmdfile=monFile['cmd'],
+ self.Map = dmonMap(giface=self._giface, cmdfile=monFile['cmd'],
mapfile = monFile['map'])
self.timer = wx.PyTimer(self.watcher)
@@ -403,19 +459,9 @@
else:
self.Map = None
- return True
-
- def CreateMapFrame(self, name, decorations=True):
- if decorations:
- toolbars = ['map']
- statusbar = True
- else:
- toolbars = []
- statusbar = False
-
self.mapFrm = DMonFrame(parent=None, id=wx.ID_ANY, title=name, Map=self.Map,
giface=self._giface, size=monSize,
- toolbars=toolbars, statusbar=statusbar)
+ toolbars=toolbars, statusbar=decorations)
# FIXME: hack to solve dependency
self._giface._mapframe = self.mapFrm
More information about the grass-commit
mailing list