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 stringtools import themes 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' class ItemDoesNotEsistWithinParent(Exception): pass 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, is_nxt_prv_item=False): return get_wrapper_class(full_path)(request, full_path, is_nxt_prv_item) 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, is_nxt_prv_item): self.request = request self.full_path = full_path self.is_nxt_prv_item = is_nxt_prv_item # 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': stringtools.physical_value_repr(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 search_query = 'tag:%s' % t.text search_url = pygal.url_userview(self.request, '', search=search_query) b.append_entry('tag-%d' % i, t.text, themes.color_icon_url(self.request, '%d.png' % (i % 10)), edit_url, True, False) if pygal.get_search_query(self.request) != search_query: b.append_entry_to_entry('tag-%d' % i, 'tagedit-%d' % i, _('Edit'), themes.gray_icon_url(self.request, 'edit2.png'), edit_url, True, False) b.append_entry_to_entry('tag-%d' % i, 'tagsearch-%d' % i, _('Search'), themes.gray_icon_url(self.request, 'search.png'), search_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): if self.is_nxt_prv_item: return pygal.url_userview(self.request, self.item.rel_path, search=pygal.SEARCH_KEEP, repeat=pygal.REPEAT_KEEP) else: return pygal.url_userview(self.request, self.item.rel_path, search=pygal.SEARCH_KEEP, repeat=pygal.REPEAT_DISABLE) @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 __parent__(self): if pygal.is_searchview(self.request) or pygal.is_favouriteview(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()) try: i = fp_il.index(self.full_path) except ValueError as e: raise ItemDoesNotEsistWithinParent(e) 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, is_nxt_prv_item=True) 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) @property def audio_information(self): rv = [] entries = ( (_('Artist'), self.item.artist_c), (_('Album'), self.item.album_c), (_('Year'), self.item.year_c), (_('Title'), self.item.title_c), (_('Duration'), stringtools.time_repr(self.item.duration_c)), ) for description, data in entries: if data is not None: rv.append({'description': description, 'data': data, 'url': None}) return rv class other_view(base_view): def __init__(self, *args, **kwargs): base_view.__init__(self, *args, **kwargs) # self.template = 'pygal/other.html'