Esempio n. 1
0
    def __init__(self):
        self.tmpl_loader = TemplateLoader(
            os.path.join(os.path.dirname(__file__), 'templates'),
            auto_reload=True,
            default_class=MarkupTemplate,
        )
        WfsConf = Pool().get('wfs.conf')
        conf = WfsConf.search([])

        if len(conf) == 0:
            self.show_non_geo = False
            self.default_geo = False
        else:
            self.show_non_geo = conf[0].show_non_geo
            self.default_geo = conf[0].default_geo

        self.url = WfsConf.get_url()
        self.model_access = Pool().get('ir.model.access')
        self.field_access = Pool().get('ir.model.field.access')
Esempio n. 2
0
    def parse(cls, report, records, data, localcontext):
        """Create QGis project file based on the selected record:
            the fields referenced in the model FIELDS variable will each have
            a separate layer in the renderd file.
        """
        User = Pool().get('res.user')
        Translation = Pool().get('ir.translation')
        filename = os.path.join(os.path.dirname(__file__), 'qgis.qgs')
        report = RelatorioReport(filename, 'text/plain', ReportFactory(), MIMETemplateLoader())

        QGisConf = Pool().get('qgis.conf')
        conf = QGisConf.search([])
        if len(conf) != 0:
            version = conf[0].version
        else:
            version = '1.9.0-Master'

        legend = OrderedDict()
        if cls.FIELDS is None:
            layers, bbox, srid = cls.get_layer(records, records[0].__name__)

            for layer in layers:
                legend[layer['title']] = layer
        else:
            layers = []
            bbox = None
            Model = Pool().get(records[0].__name__)
            for field, val in cls.FIELDS.iteritems():
                if val is None:
                    fields = [field]
                else:
                    fields = val.keys()
                sublayers = []
                for _field in fields:
                    recs = getattr(records[0], _field)
                    relation = getattr(Model, _field).model_name
                    _layers, _bbox, srid = cls.get_layer(recs, relation)
                    if _bbox is not None:
                        bbox = envelope_union(_bbox, bbox)
                    sublayers += _layers

                # Remove sublayers that are already added
                _sublayers = []
                for layer in sublayers:
                    if layer['model'] in [_layer['model'] for _layer in layers]:
                        continue
                    _sublayers.append(layer)
                sublayers = _sublayers
                layers += sublayers

                if val is None:
                    for layer in sublayers:
                        legend[layer['title']] = layer
                else:
                    if field not in legend:
                        legend[field] = OrderedDict()
                    for layer in sublayers:
                        legend[field][layer['title']] = layer

        if bbox is None:
            bbox = [
                -357823.2365,
                6037008.6939,
                1313632.3628,
                7230727.3772
            ]

        WfsConf = Pool().get('wfs.conf')
        wfs_url = WfsConf.get_url()

        localcontext.update({
            'data': data,
            'user': User(Transaction().user),
            'formatLang': cls.format_lang,
            'StringIO': StringIO.StringIO,
            'time': time,
            'datetime': datetime,
            'context': Transaction().context,
            'qgis_version': version,
            'wfs_url': wfs_url,
            'bbox': bbox,
            'srid': srid,
            'layers': layers,
            'legend': legend,
        })

        translate = TranslateFactory(cls.__name__, Transaction().language, Translation)
        localcontext['setLang'] = lambda language: translate.set_language(language)
        translator = Translator(lambda text: translate(text))
        report.filters.insert(0, translator)

        localcontext = dict(map(lambda x: (str(x[0]), x[1]), localcontext.iteritems()))

        #Test compatibility with old relatorio version <= 0.3.0
        if len(inspect.getargspec(report.__call__)[0]) == 2:
            data = report(records, **localcontext).render().getvalue()
        else:
            localcontext['objects'] = records  # XXX to remove
            localcontext['records'] = records
            data = report(**localcontext).render()
            if hasattr(data, 'getvalue'):
                data = data.getvalue()
        return ('qgs', data)
Esempio n. 3
0
    def _get_image(self, qgis_filename, composition_name):
        """Return a feature image produced by qgis wms server from a template qgis file
        containing a composion"""
        if self.geom is None:
            return buffer("")

        start = time.time()

        # retrieve attached .qgs file
        [model] = Pool().get("ir.model").search([("model", "=", self.__name__)])

        attachements = Pool().get("ir.attachment").search([("resource", "=", "ir.model,%s" % model.id)])
        attachement = None
        for att in attachements:
            if att.name == qgis_filename:
                attachement = att
                break
        if not attachement:
            self.raise_user_error("%s has no attachement %s", (self.__name__, qgis_filename))

        # get credentials for qgsi server
        config = ConfigParser.ConfigParser()
        config.read(CONFIG["qgis_server_conf"])
        username = config.get("options", "username")
        password = config.get("options", "password")

        # replace feature id in .qgs file and put credentials in
        if not self.DEBUG:
            tmpdir = tempfile.mkdtemp()
        else:
            tmpdir = "/tmp/" + qgis_filename
            if not os.path.exists(tmpdir):
                os.mkdir(tmpdir)

        os.chmod(tmpdir, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IXGRP | stat.S_IRGRP)
        dot_qgs = os.path.join(os.path.abspath(tmpdir), "proj.qgs")
        dom = xml.dom.minidom.parseString(attachement.data)

        WfsConf = Pool().get("wfs.conf")
        wfs_url = WfsConf.get_url()

        for elem in dom.getElementsByTagName("datasource"):

            basename = os.path.basename(elem.childNodes[0].data)
            for att in attachements:
                if att.name == basename:
                    filename = os.path.join(os.path.abspath(tmpdir), basename)
                    with open(filename, "wb") as image:
                        image.write(att.data)
                        elem.childNodes[0].data = filename
                    break

            # check that this is the appropriate layer
            url_parts = urlparse.urlparse(elem.childNodes[0].data)
            param = urlparse.parse_qs(url_parts[4])
            if "TYPENAME" in param and param["TYPENAME"][0].find("tryton:") != -1:
                if "FILTER" in param:
                    filt = urllib.unquote(param["FILTER"][0])
                    filt = re.sub(
                        "<ogc:Literal>.*</ogc:Literal>", "<ogc:Literal>" + str(self.id) + "</ogc:Literal>", filt
                    )
                    param.update({"FILTER": [urllib.quote(filt)]})
                param.update({"username": [username], "password": [password]})
                elem.childNodes[0].data = urlparse.urlunparse(
                    list(url_parts[0:4])
                    + ["&".join([key + "=" + ",".join(val) for key, val in param.iteritems()])]
                    + list(url_parts[5:])
                )

        # replaces images with linked ones and put them in the temp directory
        for elem in dom.getElementsByTagName("ComposerPicture"):
            basename = os.path.basename(elem.attributes["file"].value)
            for att in attachements:
                if att.name == basename:
                    image_file = os.path.join(os.path.abspath(tmpdir), basename)
                    with open(image_file, "wb") as image:
                        image.write(att.data)
                        elem.attributes["file"].value = image_file
                    break

        with codecs.open(dot_qgs, "w", "utf-8") as file_out:
            dom.writexml(file_out, indent="  ")

        # find the composer map aspect ratio and margins
        # from atlas
        map_extends = {}
        compo = dom.getElementsByTagName("Composition")[0]
        for cmap in compo.getElementsByTagName("ComposerMap"):
            ext = cmap.getElementsByTagName("Extent")[0]
            width = float(ext.attributes["xmax"].value) - float(ext.attributes["xmin"].value)
            height = float(ext.attributes["ymax"].value) - float(ext.attributes["ymin"].value)
            atlas_map = cmap.getElementsByTagName("AtlasMap")[0]
            map_extends["map" + cmap.attributes["id"].value] = {"w": width, "h": height, "margin": 0.1, "ext": ext}
            if atlas_map and atlas_map.attributes["margin"]:
                map_extends["map" + cmap.attributes["id"].value] = {
                    "w": width,
                    "h": height,
                    "margin": float(atlas_map.attributes["margin"].value),
                    "ext": ext,
                }

        layers = [layer.attributes["name"].value for layer in dom.getElementsByTagName("layer-tree-layer")]

        # compute bbox
        cursor = Transaction().cursor
        cursor.execute(
            "SELECT ST_SRID(geom), ST_Extent(geom) "
            "FROM " + self.__name__.replace(".", "_") + " WHERE id = " + str(self.id) + " GROUP BY id;"
        )

        [srid, ext] = cursor.fetchone()
        if ext:
            for name, mex in map_extends.iteritems():
                ext = ext.replace("BOX(", "").replace(")", "").replace(" ", ",")

                # ajout Pascal Obstetar pour EPSG:4326
                if srid == 4326:
                    minlat, minlong, maxlat, maxlong = ext.split(",")
                    ext = ",".join([minlong, minlat, maxlong, maxlat])

                mex["ext"] = ",".join(
                    [str(i) for i in bbox_aspect([float(i) for i in ext.split(",")], mex["w"], mex["h"], mex["margin"])]
                )

                # render image
        url = "http://localhost/cgi-bin/qgis_mapserv.fcgi?" + "&".join(
            [
                "SERVICE=WMS",
                "VERSION=1.3.0",
                "MAP=" + dot_qgs,
                "REQUEST=GetPrint",
                "FORMAT=png",
                "TEMPLATE=" + urllib.quote(composition_name.encode("utf-8")),
                "LAYER=" + ",".join([urllib.quote(l.encode("utf-8")) for l in layers[::-1]]),
                "CRS=EPSG:" + str(srid),
                "DPI=75",
            ]
            + [name + ":EXTENT=" + me["ext"] for name, me in map_extends.iteritems()]
        )
        buf = buffer(urllib.urlopen(url).read())
        print "##################### ", time.time() - start, "sec to GetPrint ", url

        if str(buf).find("ServiceException") != -1:
            self.raise_user_error("%s qgis-mapserver error:\n%s", (self.__name__, str(buf)))

        # TODO uncoment to cleanup,
        # the directory and its contend are kept for debug
        if not self.DEBUG:
            shutil.rmtree(tmpdir)

        return buf