537 rivejä
17 KiB
Python
537 rivejä
17 KiB
Python
from django.shortcuts import render
|
|
from django.utils.translation import gettext as _
|
|
import geo
|
|
import mimetypes
|
|
from ..models import get_item_type, get_item_by_rel_path, TYPE_AUDIO, TYPE_FOLDER, TYPE_IMAGE, TYPE_OTHER, TYPE_VIDEO
|
|
import os
|
|
import pygal
|
|
from ..queries import search_result_query
|
|
import random
|
|
import themes
|
|
import time
|
|
|
|
ADDTAG_ENTRY = 'addtag-main'
|
|
INFOVIEW_ENTRY = 'infoview-main'
|
|
DOWNLOAD_ENTRY = 'download-main'
|
|
DOWNLOAD_FLAT_ENTRY = 'download-flat-sub'
|
|
DOWNLOAD_STRUCT_ENTRY = 'download-struct-sub'
|
|
FAVOURITE_ENTRY = 'favourite-main'
|
|
REPEAT_ENTRY = 'repeat-main'
|
|
SHUFFLE_ENTRY = 'shuffle-main'
|
|
|
|
|
|
def get_wrapper_class(full_path):
|
|
return {
|
|
TYPE_FOLDER: folder_view,
|
|
TYPE_IMAGE: image_view,
|
|
TYPE_VIDEO: video_view,
|
|
TYPE_AUDIO: audio_view,
|
|
TYPE_OTHER: other_view,
|
|
}.get(get_item_type(full_path), base_view)
|
|
|
|
|
|
def get_wrapper_instance(full_path, request):
|
|
return get_wrapper_class(full_path)(request, full_path)
|
|
|
|
|
|
def random_copy(request, lst):
|
|
shuffle_id = pygal.get_shuffle_id(request)
|
|
#
|
|
rv = lst[:]
|
|
if shuffle_id is not None:
|
|
r = random.Random()
|
|
r.seed(shuffle_id)
|
|
r.shuffle(rv)
|
|
return rv
|
|
|
|
|
|
class base_view(object):
|
|
def __init__(self, request, full_path):
|
|
self.request = request
|
|
self.full_path = full_path
|
|
#
|
|
self.item = get_item_by_rel_path(pygal.get_rel_path(full_path))
|
|
if self.item is None:
|
|
raise LookupError("Error while initialising base_view, but item for %s does not exist." % full_path)
|
|
self.is_item = self.item.type != TYPE_FOLDER
|
|
#
|
|
self.mime_type = mimetypes.types_map.get(os.path.splitext(self.full_path)[1])
|
|
self.template = 'pygal/empty.html'
|
|
|
|
@property
|
|
def tags(self):
|
|
return self.item.tag_set.all()
|
|
|
|
def may_read(self):
|
|
return self.item.may_read(self.request.user)
|
|
|
|
def may_modify(self):
|
|
return self.item.may_modify(self.request.user)
|
|
|
|
def context_adaption(self, context):
|
|
context['item'] = self
|
|
context['thumbnail_size'] = pygal.get_thumbnail_size(self.request)
|
|
context['title'] = self.name or ''
|
|
context[context.ACTIONBAR].extend(self.actionbar)
|
|
|
|
@property
|
|
def heading(self):
|
|
return '%s' % self.item.name
|
|
|
|
@property
|
|
def general_information(self):
|
|
rv = []
|
|
full_path = pygal.get_full_path(self.item.rel_path)
|
|
rv.append({'description': _('Name'), 'data': os.path.basename(full_path), 'url': None})
|
|
rv.append({'description': _('Creation Time'), 'data': self.item.item_data.formatted_datetime, 'url': None})
|
|
rv.append({'description': _('Path'), 'data': os.path.dirname(full_path), 'url': None})
|
|
rv.append({'description': _('Size'), 'data': self.__size_txt__(self.item.item_data.size) + 'B', 'url': None})
|
|
rv.append({'description': _('UID'), 'data': self.item.current_uid(), 'url': None})
|
|
return rv
|
|
|
|
def __actionbar__(self):
|
|
b = themes.bar()
|
|
if self.is_item:
|
|
if self.is_my_favourite:
|
|
b.append_entry(
|
|
FAVOURITE_ENTRY,
|
|
'',
|
|
themes.color_icon_url(self.request, 'is_favourite.png'),
|
|
pygal.url_favourite_unset(self.request, self.item.rel_path),
|
|
True,
|
|
False
|
|
)
|
|
else:
|
|
b.append_entry(
|
|
FAVOURITE_ENTRY,
|
|
'',
|
|
themes.color_icon_url(self.request, 'favourite.png'),
|
|
pygal.url_favourite_set(self.request, self.item.rel_path),
|
|
True,
|
|
False
|
|
)
|
|
if pygal.is_infoview(self.request):
|
|
b.append_entry(
|
|
INFOVIEW_ENTRY,
|
|
_('Info'),
|
|
themes.color_icon_url(self.request, 'info.png'),
|
|
pygal.url_infoview(self.request, self.item.rel_path),
|
|
True,
|
|
True
|
|
)
|
|
else:
|
|
b.append_entry(
|
|
INFOVIEW_ENTRY,
|
|
_('Info'),
|
|
themes.color_icon_url(self.request, 'info.png'),
|
|
pygal.url_infoview(self.request, self.item.rel_path, search=pygal.SEARCH_KEEP),
|
|
True,
|
|
False
|
|
)
|
|
b.append_entry(
|
|
DOWNLOAD_ENTRY,
|
|
_('Download'),
|
|
themes.color_icon_url(self.request, 'download.png'),
|
|
pygal.url_download(self.request, self.item.rel_path),
|
|
True,
|
|
False
|
|
)
|
|
if type(self) is not folder_view:
|
|
if pygal.is_repeatview(self.request):
|
|
b.append_entry(
|
|
REPEAT_ENTRY,
|
|
_('Repeat'),
|
|
themes.color_icon_url(self.request, 'stop.png'),
|
|
pygal.url_userview(self.request, self.item.rel_path, search=pygal.SEARCH_KEEP),
|
|
True,
|
|
True
|
|
)
|
|
else:
|
|
b.append_entry(
|
|
REPEAT_ENTRY,
|
|
_('Repeat'),
|
|
themes.color_icon_url(self.request, 'play.png'),
|
|
pygal.url_repeatview(self.request, self.item.rel_path),
|
|
True,
|
|
False
|
|
)
|
|
if pygal.get_shuffle_id(self.request) is None:
|
|
b.append_entry(
|
|
SHUFFLE_ENTRY,
|
|
_('Shuffle'),
|
|
themes.color_icon_url(self.request, 'shuffle.png'),
|
|
pygal.url_userview(self.request, self.item.rel_path, shuffle=pygal.SHUFFLE_ENABLE, search=pygal.SEARCH_KEEP),
|
|
True,
|
|
False
|
|
)
|
|
else:
|
|
b.append_entry(
|
|
SHUFFLE_ENTRY,
|
|
_('Shuffle'),
|
|
themes.color_icon_url(self.request, 'shuffle.png'),
|
|
pygal.url_userview(self.request, self.item.rel_path, shuffle=pygal.SHUFFLE_DISABLE, search=pygal.SEARCH_KEEP),
|
|
True,
|
|
True
|
|
)
|
|
if self.is_item and self.may_modify():
|
|
b.append_entry(
|
|
ADDTAG_ENTRY,
|
|
_('Add Tag'),
|
|
themes.color_icon_url(self.request, 'edit2.png'),
|
|
pygal.url_addtag(self.request, self.item.rel_path),
|
|
True,
|
|
False
|
|
)
|
|
return b
|
|
|
|
@property
|
|
def is_my_favourite(self):
|
|
return self.request.user in self.item.favourite_of.all()
|
|
|
|
@property
|
|
def actionbar(self):
|
|
return self.__actionbar__()
|
|
|
|
def __tagbar__(self):
|
|
b = themes.bar(self.request)
|
|
i = 0
|
|
for t in self.item.tag_set.all():
|
|
i += 1
|
|
edit_url = pygal.url_tagedit(self.request, t.id) if self.may_modify() else None
|
|
b.append_entry('tag-%d' % i, t.text, themes.color_icon_url(self.request, '%d.png' % (i % 10)), edit_url, True, False)
|
|
return b
|
|
|
|
@property
|
|
def tagbar(self):
|
|
return self.__tagbar__()
|
|
|
|
@property
|
|
def duration(self):
|
|
return self.item.item_data.duration + 1.5
|
|
|
|
@property
|
|
def url_item(self):
|
|
return pygal.url_item(self.request, self.item.rel_path)
|
|
|
|
@property
|
|
def url_repeatview(self):
|
|
return pygal.url_repeatview(self.request, self.item.rel_path)
|
|
|
|
@property
|
|
def is_repeatview(self):
|
|
return pygal.is_repeatview(self.request)
|
|
|
|
@property
|
|
def url_thumbnail(self):
|
|
return pygal.url_thumbnail(self.request, self.item.rel_path)
|
|
|
|
@property
|
|
def url_userview(self):
|
|
return pygal.url_userview(self.request, self.item.rel_path, search=pygal.SEARCH_KEEP)
|
|
|
|
@property
|
|
def url_webnail(self):
|
|
return pygal.url_webnail(self.request, self.item.rel_path)
|
|
|
|
@property
|
|
def name(self):
|
|
return self.item.name
|
|
|
|
@property
|
|
def date_txt(self):
|
|
return self.item.item_data.formatted_datetime
|
|
|
|
def __size_txt__(self, size):
|
|
unit = {
|
|
0: '',
|
|
1: 'k',
|
|
2: 'M',
|
|
3: 'G',
|
|
4: 'T',
|
|
}
|
|
u = 0
|
|
while u < 4 and size > 1000.:
|
|
u += 1
|
|
size /= 1000.
|
|
if size < 100.:
|
|
return '%.2f %s' % (size, unit.get(u, '?'))
|
|
else:
|
|
return '%.1f %s' % (size, unit.get(u, '?'))
|
|
|
|
def __duration_txt__(self, duration):
|
|
if duration >= 3600:
|
|
return time.strftime('%H:%M:%S', time.gmtime(duration))
|
|
else:
|
|
return time.strftime('%M:%S', time.gmtime(duration))
|
|
|
|
def __parent__(self):
|
|
if pygal.is_searchview(self.request):
|
|
return query_view(self.request, search_result_query(self.request))
|
|
else:
|
|
return get_wrapper_instance(os.path.dirname(self.full_path), self.request)
|
|
|
|
def __nxt_prv__(self, direction):
|
|
if direction not in [-1, 1]:
|
|
raise ValueError("Parameter direction is incorrect: %s" % repr(direction))
|
|
fp_il = random_copy(self.request, self.__parent__().sorted_fullpathlist())
|
|
i = fp_il.index(self.full_path)
|
|
lgt = len(fp_il)
|
|
for i in range(i + direction, i + direction * lgt, direction):
|
|
full_path = fp_il[i % lgt]
|
|
if get_item_type(full_path) != TYPE_FOLDER:
|
|
return get_wrapper_instance(full_path, self.request)
|
|
return self
|
|
|
|
@property
|
|
def nxt(self):
|
|
return self.__nxt_prv__(1)
|
|
|
|
@property
|
|
def prv(self):
|
|
return self.__nxt_prv__(-1)
|
|
|
|
def render(self, context):
|
|
return render(self.request, self.template, context=context)
|
|
|
|
|
|
class query_view(object):
|
|
def __init__(self, request, query):
|
|
self.request = request
|
|
self.query = query
|
|
#
|
|
self.template = 'pygal/overview.html'
|
|
#
|
|
self.__item_list__ = None
|
|
|
|
def context_adaption(self, context):
|
|
context['item'] = self
|
|
context['thumbnail_size'] = pygal.get_thumbnail_size(self.request)
|
|
context['title'] = self.name or ''
|
|
context[context.ACTIONBAR].extend(self.actionbar)
|
|
|
|
@property
|
|
def name(self):
|
|
if pygal.is_favouriteview(self.request):
|
|
return _('My Favourites')
|
|
elif pygal.is_searchview(self.request):
|
|
return _('Search: "%s"' % pygal.get_search_query(self.request))
|
|
else:
|
|
return '-'
|
|
|
|
def __actionbar__(self):
|
|
b = themes.bar()
|
|
if pygal.is_infoview(self.request):
|
|
b.append_entry(
|
|
INFOVIEW_ENTRY,
|
|
_('Info'),
|
|
themes.color_icon_url(self.request, 'info.png'),
|
|
pygal.url_infoview(self.request, ''),
|
|
True,
|
|
True
|
|
)
|
|
else:
|
|
b.append_entry(
|
|
INFOVIEW_ENTRY,
|
|
_('Info'),
|
|
themes.color_icon_url(self.request, 'info.png'),
|
|
pygal.url_infoview(self.request, ''),
|
|
True,
|
|
False
|
|
)
|
|
b.append_entry(
|
|
DOWNLOAD_ENTRY,
|
|
_('Download'),
|
|
themes.color_icon_url(self.request, 'download.png'),
|
|
None,
|
|
True,
|
|
False
|
|
)
|
|
b.append_entry_to_entry(
|
|
DOWNLOAD_ENTRY,
|
|
DOWNLOAD_STRUCT_ENTRY,
|
|
_('Download (Structured)'),
|
|
themes.gray_icon_url(self.request, 'download.png'),
|
|
pygal.url_download(self.request, ''),
|
|
True,
|
|
False
|
|
)
|
|
b.append_entry_to_entry(
|
|
DOWNLOAD_ENTRY,
|
|
DOWNLOAD_FLAT_ENTRY,
|
|
_('Download (Flat)'),
|
|
themes.gray_icon_url(self.request, 'download.png'),
|
|
pygal.url_download(self.request, '', flat=True),
|
|
True,
|
|
False
|
|
)
|
|
if pygal.get_shuffle_id(self.request) is None:
|
|
b.append_entry(
|
|
SHUFFLE_ENTRY,
|
|
_('Shuffle'),
|
|
themes.color_icon_url(self.request, 'shuffle.png'),
|
|
pygal.url_userview(self.request, '', shuffle=pygal.SHUFFLE_ENABLE, search=pygal.SEARCH_KEEP),
|
|
True,
|
|
False
|
|
)
|
|
else:
|
|
b.append_entry(
|
|
SHUFFLE_ENTRY,
|
|
_('Shuffle'),
|
|
themes.color_icon_url(self.request, 'shuffle.png'),
|
|
pygal.url_userview(self.request, '', shuffle=pygal.SHUFFLE_DISABLE, search=pygal.SEARCH_KEEP),
|
|
True,
|
|
True
|
|
)
|
|
return b
|
|
|
|
@property
|
|
def actionbar(self):
|
|
return self.__actionbar__()
|
|
|
|
def sorted_fullpathlist(self):
|
|
il = []
|
|
for item_model in self.query:
|
|
if item_model.may_read(self.request.user):
|
|
il.append(item_model)
|
|
il.sort(key=lambda entry: entry.sort_string(), reverse=True)
|
|
return [pygal.get_full_path(i.rel_path) for i in il]
|
|
|
|
def __init_itemlist__(self):
|
|
if self.__item_list__ is None:
|
|
self.__item_list__ = []
|
|
for full_path in self.sorted_fullpathlist():
|
|
w = get_wrapper_instance(full_path, self.request)
|
|
self.__item_list__.append(w)
|
|
|
|
@property
|
|
def item_list(self):
|
|
self.__init_itemlist__()
|
|
return random_copy(self.request, self.__item_list__)
|
|
|
|
def render(self, context):
|
|
return render(self.request, self.template, context=context)
|
|
|
|
|
|
class folder_view(base_view):
|
|
def __init__(self, *args, **kwargs):
|
|
base_view.__init__(self, *args, **kwargs)
|
|
#
|
|
self.template = 'pygal/overview.html'
|
|
#
|
|
self.__item_list__ = None
|
|
|
|
def __actionbar__(self):
|
|
b = base_view.__actionbar__(self)
|
|
b.append_entry_to_entry(
|
|
DOWNLOAD_ENTRY,
|
|
DOWNLOAD_STRUCT_ENTRY,
|
|
_('Download (Structured)'),
|
|
themes.gray_icon_url(self.request, 'download.png'),
|
|
pygal.url_download(self.request, self.item.rel_path),
|
|
True,
|
|
False
|
|
)
|
|
b.append_entry_to_entry(
|
|
DOWNLOAD_ENTRY,
|
|
DOWNLOAD_FLAT_ENTRY,
|
|
_('Download (Flat)'),
|
|
themes.gray_icon_url(self.request, 'download.png'),
|
|
pygal.url_download(self.request, self.item.rel_path, flat=True),
|
|
True,
|
|
False
|
|
)
|
|
return b
|
|
|
|
def sorted_fullpathlist(self):
|
|
return [pygal.get_full_path(i.rel_path) for i in self.item.sorted_itemlist()]
|
|
|
|
def __init_fullpathlist__(self):
|
|
if self.__item_list__ is None:
|
|
self.__item_list__ = []
|
|
for full_path in self.sorted_fullpathlist():
|
|
w = get_wrapper_instance(full_path, self.request)
|
|
self.__item_list__.append(w)
|
|
|
|
@property
|
|
def item_list(self):
|
|
self.__init_fullpathlist__()
|
|
return random_copy(self.request, self.__item_list__)
|
|
|
|
@property
|
|
def url_thumbnail(self):
|
|
return pygal.url_thumbnail(self. request, self.item.thumbnail_item().rel_path)
|
|
|
|
|
|
class image_view(base_view):
|
|
def __init__(self, *args, **kwargs):
|
|
base_view.__init__(self, *args, **kwargs)
|
|
#
|
|
self.template = 'pygal/image.html'
|
|
|
|
def __actionbar__(self):
|
|
b = base_view.__actionbar__(self)
|
|
gps_data = self.item.item_data.gps
|
|
if gps_data is not None:
|
|
b.append_entry(
|
|
'actionbar-gpslink',
|
|
_('GPS'),
|
|
themes.color_icon_url(self.request, 'gps.png'),
|
|
geo.osm.landmark_link(geo.gps.coordinate(**gps_data)),
|
|
True,
|
|
False
|
|
)
|
|
return b
|
|
|
|
@property
|
|
def width(self):
|
|
if self.item.item_data.orientation in [5, 6, 7, 8]:
|
|
return self.item.item_data.height
|
|
else:
|
|
return self.item.item_data.width
|
|
|
|
@property
|
|
def height(self):
|
|
if self.item.item_data.orientation in [5, 6, 7, 8]:
|
|
return self.item.item_data.width
|
|
else:
|
|
return self.item.item_data.height
|
|
|
|
|
|
class video_view(base_view):
|
|
def __init__(self, *args, **kwargs):
|
|
base_view.__init__(self, *args, **kwargs)
|
|
#
|
|
self.template = 'pygal/video.html'
|
|
|
|
@property
|
|
def use_internal_player(self):
|
|
return self.mime_type in [mimetypes.types_map.get(ext) for ext in ['.mp4', '.webm', '.ogv', '.flv', '.3gp', ]]
|
|
|
|
@property
|
|
def webnail_width(self):
|
|
w, h = self.item.item_data.width, self.item.item_data.height
|
|
return int(pygal.get_webnail_size(self.request) * w / max(w, h))
|
|
|
|
@property
|
|
def webnail_height(self):
|
|
w, h = self.item.item_data.width, self.item.item_data.height
|
|
return int(pygal.get_webnail_size(self.request) * h / max(w, h))
|
|
|
|
|
|
class audio_view(base_view):
|
|
def __init__(self, *args, **kwargs):
|
|
base_view.__init__(self, *args, **kwargs)
|
|
#
|
|
self.template = 'pygal/audio.html'
|
|
|
|
@property
|
|
def heading(self):
|
|
return '%02d - %s' % (self.item.item_data.track, self.item.item_data.title)
|
|
|
|
|
|
class other_view(base_view):
|
|
def __init__(self, *args, **kwargs):
|
|
base_view.__init__(self, *args, **kwargs)
|
|
#
|
|
self.template = 'pygal/other.html'
|