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')
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)
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