pygal/views/__init__.py

307 lines
13 KiB
Python
Raw Normal View History

2020-01-26 23:38:32 +01:00
from ..context import context_adaption
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.http import FileResponse, HttpResponseNotAllowed
from django.shortcuts import render, HttpResponse, redirect
from django.urls.base import reverse
from django.utils.translation import gettext as _
from ..forms import TagForm
import fstools
from ..help import help_pages
from .image import get_image_instance, other
from .infoviews import get_wrapper_instance as get_infoview_wrapper_instance
import mimetypes
from ..models import get_item_by_rel_path, get_item_type, TYPE_IMAGE, Tag, Item
import os
import pygal
from ..queries import search_result_query
import tempfile
from themes import Context
from users.views import profile_pre_actions, profile_post_actions
from users.forms import UserProfileFormLanguageOnly
from .userviews import get_wrapper_instance as get_userview_wrapper_instance
import zipfile
from pygal.views.userviews import query_view
from pygal.views.image import mm_image
def pygal_item_does_not_exist(request, context):
context.set_additional_title(_('Page does not exist!'))
messages.error(request, _('The Item for the given URL does not exist.'))
return render(request, 'pygal/empty.html', context=context)
def pygal_access_denied(request, context):
context.set_additional_title(_('Access denied!'))
messages.error(request, _('Access Denied: You don\'t have access rights.'))
return render(request, 'pygal/empty.html', context=context)
def get_next(request):
if not request.POST:
return request.GET.get('next', '/')
else:
return request.POST.get('next', '/')
def pygal_responses(request, responsetype=pygal.RESP_TYPE_USERVIEW, datatype=pygal.DATA_TYPE_SEARCH, rel_path=''):
# raw and scaled items
if responsetype in [pygal.RESP_TYPE_RAWITEM, pygal.RESP_TYPE_WEBNAIL, pygal.RESP_TYPE_THUMBNAIL]:
return pygal_item(request, responsetype, rel_path)
# userview and infoview for items
elif responsetype in [pygal.RESP_TYPE_USERVIEW, pygal.RESP_TYPE_INFOVIEW] and datatype == pygal.DATA_TYPE_ITEM:
return pygal_userview_infoview(request, responsetype, rel_path)
# download
elif responsetype == pygal.RESP_TYPE_DOWNLOAD:
return pygal_download(request, datatype, rel_path)
# search
elif responsetype in [pygal.RESP_TYPE_USERVIEW, pygal.RESP_TYPE_INFOVIEW] and datatype == pygal.DATA_TYPE_SEARCH:
if not rel_path:
return pygal_search(request, rel_path)
else:
return pygal_userview_infoview(request, responsetype, rel_path)
else:
d = {
'responsetype': responsetype,
'datatype': datatype,
}
messages.error(request, _('No response implemented in pygal.views.pygal_responses for responsetype="%(responsetype)s" and datatype="%(datatype)s".') % d)
return redirect('/')
def pygal_search(request, rel_path):
context = Context(request) # needs to be executed first because of time mesurement
w = query_view(request, search_result_query(request))
context_adaption(context, request, '', wrapper_instance=w)
context.set_additional_title(w.name)
return w.render(context)
def pygal_download(request, datatype, rel_path):
full_path = pygal.get_full_path(rel_path)
if os.path.isfile(full_path):
# Download a file
temp = open(full_path, 'rb')
fn = os.path.basename(full_path)
else:
if pygal.is_favouriteview(request) or pygal.is_searchview(request) and rel_path == '':
if pygal.is_favouriteview(request):
fn = 'favourites.zip'
else:
fn = 'search.zip'
# Download the favourites or search results
fp_list = []
for i in search_result_query(request):
if i.may_read(request.user):
fp_list.append(pygal.get_full_path(i.rel_path))
else:
# Download the folder full_path
fn = (os.path.basename(full_path) or 'root') + '.zip'
fp_list = []
for i in get_item_by_rel_path(rel_path).all_itemslist():
if i.may_read(request.user):
fp_list.append(pygal.get_full_path(i.rel_path))
#
# Create the Archive from fp_list
#
flat = pygal.is_flat(request)
temp = tempfile.TemporaryFile(dir=settings.TEMP_ROOT)
archive = zipfile.ZipFile(temp, 'w', zipfile.ZIP_STORED)
for fp in fp_list:
archive.write(fp, os.path.basename(pygal.get_rel_path(fp)) if flat else pygal.get_rel_path(fp))
archive.close()
temp.seek(0)
#
# return file response
#
response = FileResponse(temp, content_type=mimetypes.types_map.get(os.path.splitext(fn)[1]))
response['Content-Disposition'] = 'attachment; filename="%s"' % fn
return response
def pygal_helpview(request, page='main'):
context = Context(request) # needs to be executed first because of time mesurement
help_content = help_pages[page]
context_adaption(
context, # the base context
request, # the request object to be used in context_adaption
rel_path='', # the current help_page to identify which taskbar entry has to be highlighted
title=_('Help'), # the title for the page (template)
current_help_page=page,
)
context['help_content'] = help_content # the help content itself (template)
return render(request, 'pygal/help.html', context=context)
context = Context(request) # needs to be executed first because of time mesurement
context_adaption(context, request, '', title=_('Help'))
return help_data(request, context)
def pygal_userview_infoview(request, responsetype, rel_path):
context = Context(request) # needs to be executed first because of time mesurement
full_path = pygal.get_full_path(rel_path)
try:
if responsetype == pygal.RESP_TYPE_INFOVIEW:
w = get_infoview_wrapper_instance(full_path, request)
else:
w = get_userview_wrapper_instance(full_path, request)
except LookupError:
context_adaption(context, request, '')
return pygal_item_does_not_exist(request, context)
context_adaption(context, request, rel_path, wrapper_instance=w)
#
if w.may_read():
context.set_additional_title(w.name)
return w.render(context)
else:
return pygal_access_denied(request, context)
def pygal_item(request, responsetype, rel_path):
full_path = pygal.get_full_path(rel_path)
i = get_item_by_rel_path(rel_path)
if not i.may_read(request.user):
im = other(full_path, request) # This will return a mime icon instead of the image itself
else:
im = get_image_instance(full_path, request)
#
if responsetype == pygal.RESP_TYPE_THUMBNAIL:
return HttpResponse(im.thumbnail_picture(), content_type=im.mime_type_xnails)
elif responsetype == pygal.RESP_TYPE_WEBNAIL:
return HttpResponse(im.webnail_picture(), content_type=im.mime_type_xnails)
else:
if i.may_read(request.user):
mimetypes.init()
mime_type = mimetypes.types_map.get(os.path.splitext(full_path)[1])
data = open(full_path, 'rb').read()
return HttpResponse(data, content_type=mime_type)
else:
im = mm_image(os.path.join(os.path.dirname(__file__), 'forbidden.png'))
if responsetype == pygal.RESP_TYPE_THUMBNAIL:
im.resize(int(pygal.get_thumbnail_size(request) * .75))
return HttpResponse(im.image_data(), content_type='image/png')
@login_required
def pygal_profile(request):
context = Context(request) # needs to be executed first because of time mesurement
current_thumbnail_size = pygal.get_thumbnail_size(request)
current_webnail_size = pygal.get_webnail_size(request)
profile_pre_actions(request, context, UserProfileFormLanguageOnly)
context_adaption(context, request, '', title=_('Profile for %(username)s') % {'username': request.user.username})
context['THUMBNAIL_SIZES'] = settings.THUMBNAIL_SIZES
context['thumbnail_size'] = current_thumbnail_size
context['WEBNAIL_SIZES'] = settings.WEBNAIL_SIZES
context['webnail_size'] = current_webnail_size
if request.POST:
# store thumbnail size, if changed
thumbnail_size = int(request.POST.get('thumbnail_size'))
if current_thumbnail_size != thumbnail_size:
pygal.set_thumbnail_size(request, thumbnail_size)
current_thumbnail_size = thumbnail_size
messages.info(request, _('The Thumbnail Size was set to "%d"') % (thumbnail_size))
# store webnail size, if changed
webnail_size = int(request.POST.get('webnail_size'))
if current_webnail_size != webnail_size:
pygal.set_webnail_size(request, webnail_size)
current_webnail_size = webnail_size
messages.info(request, _('The Webnail Size was set to "%d"') % (webnail_size))
return profile_post_actions(request, context)
else:
return render(request, 'pygal/profile.html', context=context)
def tag_context_adaption(context, w, request, enable_tag_area_selection):
context['item'] = w
context['next'] = get_next(request)
context['enable_tag_area_selection'] = enable_tag_area_selection
if enable_tag_area_selection:
i_w, i_h = w.width, w.height
max_size = int(pygal.get_webnail_size(request) / 2)
factor_to_original = max(i_w, i_h) / max_size
context['factor_to_original'] = factor_to_original
context['tag_img_width'] = int(i_w / factor_to_original)
context['tag_img_height'] = int(i_h / factor_to_original)
def pygal_addtag(request, rel_path):
context = Context(request) # needs to be executed first because of time mesurement
full_path = pygal.get_full_path(rel_path)
w = get_userview_wrapper_instance(full_path, request)
if not w.may_modify():
messages.error(request, _('You don\'t have the rights to add a Tag to this Item.'))
return redirect(get_next(request))
else:
context_adaption(
context,
request,
rel_path,
title=_('Add Tag for %s') % w.name
)
tag_context_adaption(context, w, request, get_item_type(full_path) in [TYPE_IMAGE])
if request.POST:
tag = Tag(item=w.item)
form = TagForm(request.POST, instance=tag, factor_to_original=context['factor_to_original'])
if form.is_valid():
form.save()
messages.info(request, _('Thanks for adding a Tag to %s') % w.name)
return redirect(get_next(request))
else:
form = TagForm(factor_to_original=context['factor_to_original'])
context['form'] = form
return render(request, 'pygal/tagedit.html', context=context)
def pygal_tagedit(request, tag_id):
context = Context(request) # needs to be executed first because of time mesurement
try:
t = Tag.objects.get(pk=tag_id)
except Tag.DoesNotExist:
messages.error(request, _('Tag %d does not exist!') % tag_id)
return redirect(get_next(request))
if not t.item.may_modify(request.user):
messages.error(request, _('You don\'t have the rights to change Tag %(tag_id)d.') % {'tag_id': tag_id})
return redirect(get_next(request))
else:
w = get_userview_wrapper_instance(pygal.get_full_path(t.item.rel_path), request)
context_adaption(
context,
request,
t.item.rel_path,
title=_('Edit Tag %(tag_id)d for %(item_name)s') % {'tag_id': tag_id, 'item_name': w.name}
)
tag_context_adaption(context, w, request, t.item.type in [TYPE_IMAGE])
context['enable_delete_button'] = True
if request.POST:
if request.POST.get('save'):
form = TagForm(request.POST, instance=t, factor_to_original=context['factor_to_original'])
if form.is_valid():
form.save()
messages.info(request, _('Thanks for editing Tag %(tag_id)d to %(item_name)s') % {'tag_id': tag_id, 'item_name': w.name})
return redirect(get_next(request))
else:
t.delete()
messages.info(request, _('Tag %(tag_id)d of %(item_name)s has been deleted.') % {'tag_id': tag_id, 'item_name': w.name})
return redirect(get_next(request))
else:
form = TagForm(instance=t, factor_to_original=context['factor_to_original'])
context['form'] = form
return render(request, 'pygal/tagedit.html', context=context)
def pygal_favourite(request, set_favourite, rel_path):
nxt = request.GET.get('next', '/')
item = get_item_by_rel_path(rel_path)
if not set_favourite and request.user in item.favourite_of.all():
item.favourite_of.remove(request.user)
item.save()
if nxt.startswith(pygal.url_favouriteview(request)):
nxt = pygal.url_favouriteview(request)
elif set_favourite and request.user not in item.favourite_of.all():
item.favourite_of.add(request.user)
item.save()
else:
messages.error(request, 'Favourite setting is already in targetstate!')
return redirect(nxt + '#%s' % item.name)