|
|
from django.core.files.images import get_image_dimensions
|
|
|
from django.template.defaultfilters import filesizeformat
|
|
|
from django.contrib.staticfiles.templatetags.staticfiles import static
|
|
|
|
|
|
FILE_STUB_IMAGE = 'images/file.png'
|
|
|
FILE_STUB_URL = 'images/url.png'
|
|
|
|
|
|
FILE_TYPES_VIDEO = (
|
|
|
'webm',
|
|
|
'mp4',
|
|
|
'mpeg',
|
|
|
'ogv',
|
|
|
)
|
|
|
FILE_TYPE_SVG = 'svg'
|
|
|
FILE_TYPES_AUDIO = (
|
|
|
'ogg',
|
|
|
'mp3',
|
|
|
'opus',
|
|
|
)
|
|
|
FILE_TYPES_IMAGE = (
|
|
|
'jpeg',
|
|
|
'jpg',
|
|
|
'png',
|
|
|
'bmp',
|
|
|
'gif',
|
|
|
)
|
|
|
|
|
|
PLAIN_FILE_FORMATS = {
|
|
|
'pdf': 'pdf',
|
|
|
'djvu': 'djvu',
|
|
|
'txt': 'txt',
|
|
|
'tex': 'tex',
|
|
|
'xcf': 'xcf',
|
|
|
}
|
|
|
|
|
|
CSS_CLASS_IMAGE = 'image'
|
|
|
CSS_CLASS_THUMB = 'thumb'
|
|
|
|
|
|
|
|
|
def get_viewers():
|
|
|
return AbstractViewer.__subclasses__()
|
|
|
|
|
|
|
|
|
class AbstractViewer:
|
|
|
def __init__(self, file, file_type, hash, url):
|
|
|
self.file = file
|
|
|
self.file_type = file_type
|
|
|
self.hash = hash
|
|
|
self.url = url
|
|
|
|
|
|
@staticmethod
|
|
|
def supports(file_type):
|
|
|
return True
|
|
|
|
|
|
def get_view(self):
|
|
|
return '<div class="image">'\
|
|
|
'{}'\
|
|
|
'<div class="image-metadata"><a href="{}" download >{}, {}</a></div>'\
|
|
|
'</div>'.format(self.get_format_view(), self.file.url,
|
|
|
self.file_type, filesizeformat(self.file.size))
|
|
|
|
|
|
def get_format_view(self):
|
|
|
if self.file_type in PLAIN_FILE_FORMATS:
|
|
|
image = 'images/fileformats/{}.png'.format(
|
|
|
PLAIN_FILE_FORMATS[self.file_type])
|
|
|
else:
|
|
|
image = FILE_STUB_IMAGE
|
|
|
|
|
|
return '<a href="{}">'\
|
|
|
'<img class="url-image" src="{}" width="200" height="150"/>'\
|
|
|
'</a>'.format(self.file.url, static(image))
|
|
|
|
|
|
|
|
|
class VideoViewer(AbstractViewer):
|
|
|
@staticmethod
|
|
|
def supports(file_type):
|
|
|
return file_type in FILE_TYPES_VIDEO
|
|
|
|
|
|
def get_format_view(self):
|
|
|
return '<video width="200" height="150" controls src="{}"></video>'\
|
|
|
.format(self.file.url)
|
|
|
|
|
|
|
|
|
class AudioViewer(AbstractViewer):
|
|
|
@staticmethod
|
|
|
def supports(file_type):
|
|
|
return file_type in FILE_TYPES_AUDIO
|
|
|
|
|
|
def get_format_view(self):
|
|
|
return '<audio controls src="{}"></audio>'.format(self.file.url)
|
|
|
|
|
|
|
|
|
class SvgViewer(AbstractViewer):
|
|
|
@staticmethod
|
|
|
def supports(file_type):
|
|
|
return file_type == FILE_TYPE_SVG
|
|
|
|
|
|
def get_format_view(self):
|
|
|
return '<a class="thumb" href="{}">'\
|
|
|
'<img class="post-image-preview" width="200" height="150" src="{}" />'\
|
|
|
'</a>'.format(self.file.url, self.file.url)
|
|
|
|
|
|
|
|
|
class ImageViewer(AbstractViewer):
|
|
|
@staticmethod
|
|
|
def supports(file_type):
|
|
|
return file_type in FILE_TYPES_IMAGE
|
|
|
|
|
|
def get_format_view(self):
|
|
|
metadata = '{}, {}'.format(self.file.name.split('.')[-1],
|
|
|
filesizeformat(self.file.size))
|
|
|
width, height = get_image_dimensions(self.file.file)
|
|
|
preview_path = self.file.path.replace('.', '.200x150.')
|
|
|
pre_width, pre_height = get_image_dimensions(preview_path)
|
|
|
|
|
|
split = self.file.url.rsplit('.', 1)
|
|
|
w, h = 200, 150
|
|
|
thumb_url = '%s.%sx%s.%s' % (split[0], w, h, split[1])
|
|
|
|
|
|
return '<a class="{}" href="{full}">' \
|
|
|
'<img class="post-image-preview"' \
|
|
|
' src="{}"' \
|
|
|
' alt="{}"' \
|
|
|
' width="{}"' \
|
|
|
' height="{}"' \
|
|
|
' data-width="{}"' \
|
|
|
' data-height="{}" />' \
|
|
|
'</a>' \
|
|
|
.format(CSS_CLASS_THUMB,
|
|
|
thumb_url,
|
|
|
self.hash,
|
|
|
str(pre_width),
|
|
|
str(pre_height), str(width), str(height),
|
|
|
full=self.file.url, image_meta=metadata)
|
|
|
|
|
|
|
|
|
class UrlViewer(AbstractViewer):
|
|
|
@staticmethod
|
|
|
def supports(file_type):
|
|
|
return file_type is None
|
|
|
|
|
|
def get_view(self):
|
|
|
return '<div class="image">' \
|
|
|
'{}' \
|
|
|
'</div>'.format(self.get_format_view())
|
|
|
def get_format_view(self):
|
|
|
return '<a href="{}">' \
|
|
|
'<img class="url-image" src="{}" width="200" height="150"/>' \
|
|
|
'</a>'.format(self.url, static(FILE_STUB_URL))
|
|
|
|