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) """ Map.__init__(self) self._giface = giface # environment settings self.env = dict() self.cmdfile = cmdfile # list of layers for rendering added from cmd file # TODO temporary solution, layer management by different tools in GRASS # should be resolved self.ownedLayers = [] self.oldOverlays = [] if mapfile: self.mapfileCmd = mapfile self.maskfileCmd = os.path.splitext(mapfile)[0] + '.pgm' # generated file for g.pnmcomp output for rendering the map self.mapfile = monFile['map'] if os.path.splitext(self.mapfile)[1] != '.ppm': self.mapfile += '.ppm' # signal sent when d.out.file/d.to.rast appears in cmd file, attribute # is cmd self.saveToFile = Signal('DMonMap.saveToFile') self.dToRast = Signal('DMonMap.dToRast') # signal sent when d.what.rast/vect appears in cmd file, attribute is # cmd self.query = Signal('DMonMap.query') self.renderMgr = RenderMapMgr(self) # update legend file variable with the one d.mon uses with open(monFile['env'], 'r') as f: lines = f.readlines() for line in lines: if 'GRASS_LEGEND_FILE' in line: legfile = line.split('=', 1)[1].strip() self.renderMgr.UpdateRenderEnv( {'GRASS_LEGEND_FILE': legfile}) break
class DMonMap(Map): 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) """ Map.__init__(self) self._giface = giface # environment settings self.env = dict() self.cmdfile = cmdfile # list of layers for rendering added from cmd file # TODO temporary solution, layer management by different tools in GRASS # should be resolved self.ownedLayers = [] self.oldOverlays = [] if mapfile: self.mapfileCmd = mapfile self.maskfileCmd = os.path.splitext(mapfile)[0] + '.pgm' # generated file for g.pnmcomp output for rendering the map self.mapfile = monFile['map'] if os.path.splitext(self.mapfile)[1] != '.ppm': self.mapfile += '.ppm' # signal sent when d.out.file/d.to.rast appears in cmd file, attribute # is cmd self.saveToFile = Signal('DMonMap.saveToFile') self.dToRast = Signal('DMonMap.dToRast') # signal sent when d.what.rast/vect appears in cmd file, attribute is # cmd self.query = Signal('DMonMap.query') self.renderMgr = RenderMapMgr(self) # update legend file variable with the one d.mon uses with open(monFile['env'], 'r') as f: lines = f.readlines() for line in lines: if 'GRASS_LEGEND_FILE' in line: legfile = line.split('=', 1)[1].strip() self.renderMgr.UpdateRenderEnv( {'GRASS_LEGEND_FILE': legfile}) break def GetLayersFromCmdFile(self): """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'): dCmd = lines[-1].strip() fd = open(self.cmdfile, 'w') fd.writelines(lines[:-1]) fd.close() if lines[-1].startswith('d.out.file'): self.saveToFile.emit(cmd=utils.split(dCmd)) else: self.dToRast.emit(cmd=utils.split(dCmd)) return if lines[-1].startswith('d.what'): dWhatCmd = lines[-1].strip() fd = open(self.cmdfile, 'w') fd.writelines(lines[:-1]) fd.close() if '=' in utils.split(dWhatCmd)[1]: maps = utils.split(dWhatCmd)[1].split('=')[1].split( ',') else: maps = utils.split(dWhatCmd)[1].split(',') self.query.emit( ltype=utils.split(dWhatCmd)[0].split('.')[-1], maps=maps) return else: # clean overlays after erase self.oldOverlays = [] overlays = list( self._giface.GetMapDisplay().decorations.keys()) for each in overlays: self._giface.GetMapDisplay().RemoveOverlay(each) existingLayers = self.GetListOfLayers() # holds new rendreing order for every layer in existingLayers layersOrder = [-1] * len(existingLayers) # next number in rendering order next_layer = 0 mapFile = None render_env = dict() for line in lines: if line.startswith('#'): if 'GRASS_RENDER_FILE' in line: mapFile = line.split('=', 1)[1].strip() try: k, v = line[2:].strip().split('=', 1) except: pass render_env[k] = v continue 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] args = {} if ltype in ('barscale', 'rastleg', 'northarrow', 'text', 'vectleg'): # TODO: this is still not optimal # it is there to prevent adding the same overlay multiple times if cmd in self.oldOverlays: continue if ltype == 'rastleg': self._giface.GetMapDisplay().AddLegendRast(cmd=cmd) elif ltype == 'barscale': self._giface.GetMapDisplay().AddBarscale(cmd=cmd) elif ltype == 'northarrow': self._giface.GetMapDisplay().AddArrow(cmd=cmd) elif ltype == 'text': self._giface.GetMapDisplay().AddDtext(cmd=cmd) elif ltype == 'vectleg': self._giface.GetMapDisplay().AddLegendVect(cmd=cmd) self.oldOverlays.append(cmd) continue classLayer = MapLayer args['ltype'] = ltype exists = False for i, layer in enumerate(existingLayers): if layer.GetCmd(string=True) == utils.GetCmdString( cmdlist_to_tuple(cmd)): exists = True if layersOrder[i] == -1: layersOrder[i] = next_layer next_layer += 1 # layer must be put higher in render order (same cmd was insered more times) # TODO delete rendurant cmds from cmd file? else: for j, l_order in enumerate(layersOrder): if l_order > layersOrder[i]: layersOrder[j] -= 1 layersOrder[i] = next_layer - 1 break if exists: continue mapLayer = classLayer(name=name, cmd=cmd, Map=None, hidden=True, render=False, mapfile=mapFile, **args) mapLayer.GetRenderMgr().updateProgress.connect( self.GetRenderMgr().ReportProgress) if render_env: mapLayer.GetRenderMgr().UpdateRenderEnv(render_env) render_env = dict() newLayer = self._addLayer(mapLayer) existingLayers.append(newLayer) self.ownedLayers.append(newLayer) layersOrder.append(next_layer) next_layer += 1 nlayers += 1 reorderedLayers = [-1] * next_layer for i, layer in enumerate(existingLayers): # owned layer was not found in cmd file -> is deleted if layersOrder[i] == -1 and layer in self.ownedLayers: self.ownedLayers.remove(layer) self.DeleteLayer(layer) # other layer e. g. added by wx.vnet are added to the top elif layersOrder[i] == -1 and layer not in self.ownedLayers: reorderedLayers.append(layer) # 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(render=False) def Render(self, *args, **kwargs): """Render layer to image. For input params and returned data see overridden method in Map class. """ return Map.Render(self, *args, **kwargs) def AddLayer(self, *args, **kwargs): """Adds generic map layer to list of layers. For input params and returned data see overridden method in Map class. """ driver = UserSettings.Get(group='display', key='driver', subkey='type') if driver == 'png': os.environ["GRASS_RENDER_IMMEDIATE"] = "png" else: os.environ["GRASS_RENDER_IMMEDIATE"] = "cairo" layer = Map.AddLayer(self, *args, **kwargs) del os.environ["GRASS_RENDER_IMMEDIATE"] return layer