Пример #1
0
    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
Пример #2
0
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