terom@141: """ terom@141: Image handling. terom@141: """ terom@141: terom@141: terom@141: from werkzeug import Request, Response, exceptions terom@141: from werkzeug.utils import html terom@141: terom@141: import pngtile.tile terom@141: from pngtile.application import BaseApplication terom@141: import pypngtile terom@141: terom@141: import json terom@147: import os, os.path terom@147: terom@147: def dir_url (prefix, name, item): terom@147: """ terom@147: Join together an absolute URL prefix, an optional directory name, and a directory item terom@147: """ terom@147: terom@147: url = prefix terom@147: terom@147: if name: terom@147: url += '/' + name terom@147: terom@147: url += '/' + item terom@147: terom@147: return url terom@147: terom@147: def dir_list (root): terom@147: """ terom@147: Yield a series of directory items to show for the given dir terom@147: """ terom@147: terom@147: for name in os.listdir(root): terom@147: path = os.path.join(root, name) terom@147: terom@147: # skip dotfiles terom@147: if name.startswith('.'): terom@147: continue terom@147: terom@147: # show dirs terom@147: if os.path.isdir(path): terom@147: yield name terom@147: terom@147: # examine ext terom@147: if '.' in name: terom@147: name_base, name_type = name.rsplit('.', 1) terom@147: else: terom@147: name_base = name terom@147: name_type = None terom@147: terom@147: # show .png files with a .cache file terom@147: if name_type in ImageApplication.IMAGE_TYPES and os.path.exists(os.path.join(root, name_base + '.cache')): terom@147: yield name terom@141: terom@141: class ImageApplication (BaseApplication): terom@141: terom@141: STYLESHEETS = ( terom@141: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css', terom@141: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css', terom@141: 'http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css', terom@142: '/static/pngtile/map.css', terom@141: ) terom@141: terom@141: SCRIPTS = ( terom@141: 'https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js', terom@141: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js', terom@141: 'http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js', terom@142: '/static/pngtile/map.js', terom@141: ) terom@141: terom@141: def __init__ (self, **opts): terom@141: BaseApplication.__init__(self, **opts) terom@141: terom@147: def render_dir_breadcrumb (self, name): terom@147: path = [] terom@147: terom@147: yield html.li(html.a(href='/', *[u"Index"])) terom@147: terom@147: if name: terom@147: for part in name.split('/'): terom@147: path.append(part) terom@147: terom@147: yield html.li(html.a(href='/'.join(path), *[part])) terom@147: terom@147: def render_dir (self, request, name, items): terom@147: """ terom@147: request: werkzeug.Request terom@147: name: /.../... url to dir terom@147: items: [...] items in dir terom@147: """ terom@147: terom@147: if name: terom@147: title = name terom@147: else: terom@147: title = "Index" terom@147: terom@147: return self.render_html( terom@147: title = name, terom@147: body = ( terom@147: html.div(class_='container', *[ terom@147: html.h1(title), terom@147: html.div(*[ terom@147: html.ol(class_='breadcrumb', *self.render_dir_breadcrumb(name)), terom@147: ]), terom@147: html.div(class_='list', *[ terom@147: html.ul(class_='list-group', *[html.li(class_='list-group-item', *[ terom@147: html.a(href=dir_url('', name, item), *[item]) terom@147: ]) for item in items] terom@147: ), terom@147: ]), terom@147: ]), terom@147: ), terom@147: ) terom@147: terom@141: def render_image (self, request, image, name): terom@141: """ terom@141: request: werkzeug.Request terom@141: image: pypngtile.Image terom@141: name: request path for .png image terom@141: """ terom@141: terom@141: image_info = image.info() terom@141: terom@142: map_config = dict( terom@141: tile_url = 'http://zovoweix.qmsk.net:8080/{name}?x={x}&y={y}&zoom={z}', terom@141: tile_name = name, terom@141: terom@141: tile_size = pngtile.tile.TILE_SIZE, terom@141: tile_zoom = pngtile.tile.MAX_ZOOM, terom@141: terom@145: image_url = 'http://zovoweix.qmsk.net:8080/{name}?w={w}&h={h}&x={x}&y={y}&zoom={z}', terom@145: image_name = name, terom@141: image_width = image_info['img_width'], terom@141: image_height = image_info['img_height'], terom@141: ) terom@141: terom@141: return self.render_html( terom@141: title = name, terom@141: body = ( terom@141: html.div(id='wrapper', *[ terom@141: html.div(id='map') terom@141: ]), terom@141: ), terom@141: end = ( terom@142: html.script("""$(function() {{ map_init({map_config}); }});""".format(map_config=json.dumps(map_config))), terom@141: ), terom@141: ) terom@141: terom@147: def handle_dir (self, request, name, path): terom@141: """ terom@147: Generate response for directory listing. terom@141: """ terom@147: terom@147: items = sorted(dir_list(path)) terom@147: terom@147: html = self.render_dir(request, name, items) terom@147: terom@147: return Response(html, content_type="text/html") terom@147: terom@147: def handle_image (self, request, name, path): terom@147: """ terom@147: Generate Response for image request. terom@147: """ terom@147: terom@141: try: terom@141: image, name = self.get_image(request.path) terom@141: except pypngtile.Error as error: terom@141: raise exceptions.BadRequest(str(error)) terom@141: terom@141: html = self.render_image(request, image, name) terom@141: terom@141: return Response(html, content_type="text/html") terom@141: terom@147: def handle (self, request): terom@147: """ terom@147: Handle request for an image terom@147: """ terom@141: terom@147: name, path = self.lookup_path(request.path) terom@147: terom@147: # determine type terom@147: if '/' in name: terom@147: _, name_base = name.rsplit('/', 1) terom@147: else: terom@147: name_base = name terom@147: terom@147: if '.' in name_base: terom@147: name_base, name_type = name_base.rsplit('.', 1) terom@147: else: terom@147: name_type = None terom@147: terom@147: # determine handler terom@147: if os.path.isdir(path): terom@147: return self.handle_dir(request, name, path) terom@147: terom@147: elif name_type and name_type in self.IMAGE_TYPES: terom@147: return self.handle_image(request, name, path) terom@147: terom@147: else: terom@147: raise exceptions.NotFound(path) terom@147: