import os
import gws.common.model
import gws.tools.mime
import gws.types as t
#:export
[docs]class TemplateQualityLevel(t.Data):
"""Quality level for a template"""
name: str = '' #: level name
dpi: int #: dpi value
[docs]class Config(t.WithType):
dataModel: t.Optional[gws.common.model.Config] #: user-editable template attributes
mimeTypes: t.Optional[t.List[str]] #: mime types this template can generate
path: t.Optional[t.FilePath] #: path to a template file
subject: str = '' #: template purpose
qualityLevels: t.Optional[t.List[t.TemplateQualityLevel]] #: list of quality levels supported by the template
text: str = '' #: template content
title: str = '' #: template title
#:export
[docs]class TemplateProps(t.Props):
uid: str
title: str
qualityLevels: t.List[t.TemplateQualityLevel]
mapHeight: int
mapWidth: int
dataModel: t.ModelProps
#:export
[docs]class TemplateOutput(t.Data):
mime: str
content: str
path: str
#:export
[docs]class TemplateLegendMode(t.Enum):
html = 'html'
image = 'image'
#:export ITemplate
[docs]class Object(gws.Object, t.ITemplate):
map_size: t.Size
page_size: t.Size
legend_mode: t.Optional[t.TemplateLegendMode]
legend_layer_uids: t.List[str]
@property
def props(self):
return t.TemplateProps(
uid=self.uid,
title=self.title,
qualityLevels=self.var('qualityLevels', default=[]),
dataModel=self.data_model,
mapWidth=self.map_size[0],
mapHeight=self.map_size[1],
pageWidth=self.page_size[0],
pageHeight=self.page_size[1],
)
[docs] def dpi_for_quality(self, quality):
q = self.var('qualityLevels')
if q and quality < len(q):
return q[quality].dpi
return 0
[docs] def normalize_context(self, context: dict) -> dict:
if not self.data_model:
return context
atts = self.data_model.apply_to_dict(context)
return {a.name: a.value for a in atts}
[docs] def render(self, context: dict, mro: t.MapRenderOutput = None, out_path: str = None, legends: dict = None, format: str = None) -> t.TemplateOutput:
pass
# @TODO template types should be configurable
_types = {
'.cx.html': 'html',
'.cx.csv': 'csv',
'.qgs': 'qgis',
'.cx.xml': 'xml',
}
def _type_from_path(path):
for ext, tt in _types.items():
if path.endswith(ext):
return tt
[docs]def from_path(root, path, shared=True):
tt = _type_from_path(path)
if not tt:
return
cfg = t.Config(type=tt, path=path)
return from_config(root, cfg, shared=shared)
[docs]def from_config(root, cfg, shared: bool = False, parent: t.IObject = None) -> t.ITemplate:
if not shared:
return t.cast(t.ITemplate, root.create_object('gws.ext.template', cfg, parent))
uid = gws.get(cfg, 'uid') or gws.get(cfg, 'path') or gws.sha256(gws.get(cfg, 'text') or '')
tpl = t.cast(t.ITemplate, root.create_shared_object('gws.ext.template', uid, cfg))
if parent:
parent.append_child(tpl)
return tpl
_dir = os.path.dirname(__file__) + '/builtin_templates/'
BUILTINS = [
t.Config(
type='html',
path=_dir + '/layer_description.cx.html',
subject='layer.description',
),
t.Config(
type='html',
path=_dir + '/project_description.cx.html',
subject='project.description',
),
t.Config(
type='html',
path=_dir + '/feature_description.cx.html',
subject='feature.description',
),
t.Config(
type='html',
path=_dir + '/feature_teaser.cx.html',
subject='feature.teaser',
),
]
[docs]def bundle(
target: t.IObject,
configs: t.List[t.ext.template.Config],
defaults: t.List[t.ext.template.Config] = None,
) -> t.List[t.ITemplate]:
ts = []
for cfg in (configs or []):
ts.append(from_config(target.root, cfg, shared=False, parent=target))
for cfg in (defaults or []):
ts.append(from_config(target.root, cfg, shared=True, parent=target))
return ts
[docs]def find(templates: t.List[t.ITemplate], subject: str = None, category: str = None, mime: str = None) -> t.Optional[t.ITemplate]:
for tpl in templates:
ok = (
(not subject or subject == tpl.subject)
and (not category or category == tpl.category)
and (not mime or mime in tpl.mime_types))
if ok:
return tpl