OpenSlides/openslides/projector/views.py
2012-08-15 13:42:25 +02:00

410 lines
13 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
openslides.projector.views
~~~~~~~~~~~~~~~~~~~~~~~~~~
Views for the projector app.
:copyright: 2011, 2012 by OpenSlides team, see AUTHORS.
:license: GNU GPL, see LICENSE for more details.
"""
from datetime import datetime
from time import time
from django.conf import settings
from django.contrib import messages
from django.core.urlresolvers import reverse
from django.db import transaction
from django.db.models import Q
from django.dispatch import receiver
from django.utils.datastructures import SortedDict
from django.utils.importlib import import_module
from django.utils.translation import ugettext_lazy as _
from openslides.utils.template import render_block_to_string, Tab
from openslides.utils.utils import html_strong
from openslides.utils.views import (TemplateView, RedirectView, CreateView,
UpdateView, DeleteView, AjaxMixin)
from openslides.config.models import config
from openslides.projector.api import (get_active_slide, set_active_slide,
projector_message_set, projector_message_delete, get_slide_from_sid,
get_all_widgets)
from openslides.projector.forms import SelectWidgetsForm
from openslides.projector.models import ProjectorOverlay, ProjectorSlide
from openslides.projector.projector import SLIDE, Widget
from openslides.projector.signals import projector_overlays
class DashboardView(TemplateView, AjaxMixin):
"""
Overview over all possible slides, the overlays and a liveview.
"""
template_name = 'projector/dashboard.html'
permission_required = 'projector.can_see_dashboard'
def post(self, request, *args, **kwargs):
# TODO: Try to put this code in the widget
if 'message' in request.POST:
projector_message_set(request.POST['message_text'])
elif 'message-clean' in request.POST:
projector_message_delete()
if request.is_ajax():
return self.ajax_get(request, *args, **kwargs)
return self.get(request, *args, **kwargs)
def get_ajax_context(self, **kwargs):
return {
'overlay_message': config['projector_message'],
}
def get_context_data(self, **kwargs):
context = super(DashboardView, self).get_context_data(**kwargs)
context['widgets'] = get_all_widgets(self.request, session=True)
return context
class Projector(TemplateView, AjaxMixin):
"""
The Projector-Page.
"""
permission_required = 'projector.can_see_projector'
@property
def data(self):
try:
return self._data
except AttributeError:
pass
sid = self.kwargs['sid']
if sid is None:
try:
data = get_active_slide()
except AttributeError: #TODO: It has to be an Slide.DoesNotExist
data = None
ajax = 'on'
else:
data = get_slide_from_sid(sid)
ajax = 'off'
if data is None:
data = {
'title': config['event_name'],
'template': 'projector/default.html',
}
data['overlays'] = []
data['ajax'] = ajax
# Projector Overlays
if self.kwargs['sid'] is None:
active_defs = ProjectorOverlay.objects.filter(active=True) \
.filter(Q(sid=sid) | Q(sid=None)).values_list('def_name',
flat=True)
for receiver, response in projector_overlays.send(sender=sid,
register=False, call=active_defs):
if response is not None:
data['overlays'].append(response)
self._data = data
return data
def get_template_names(self):
return [self.data['template']]
def get_context_data(self, **kwargs):
context = super(Projector, self).get_context_data(**kwargs)
context.update(self.data)
return context
def get_ajax_context(self, **kwargs):
content = render_block_to_string(self.get_template_names()[0],
'content', self.data)
scrollcontent = render_block_to_string(self.get_template_names()[0],
'scrollcontent', self.data)
context = super(Projector, self).get_ajax_context(**kwargs)
content_hash = hash(content)
context.update({
'content': content,
'scrollcontent': scrollcontent,
'time': datetime.now().strftime('%H:%M'),
'overlays': self.data['overlays'],
'title': self.data['title'],
'bigger': config['bigger'],
'up': config['up'],
'content_hash': content_hash,
})
return context
def get(self, request, *args, **kwargs):
if request.is_ajax():
return self.ajax_get(request, *args, **kwargs)
return super(Projector, self).get(request, *args, **kwargs)
class ActivateView(RedirectView):
"""
Activate a Slide.
"""
permission_required = 'projector.can_manage_projector'
url = 'dashboard'
allow_ajax = True
def pre_redirect(self, request, *args, **kwargs):
try:
set_active_slide(kwargs['sid'], kwargs['argument'])
except KeyError:
set_active_slide(kwargs['sid'])
config['up'] = 0
config['bigger'] = 100
class SelectWidgetsView(TemplateView):
"""
Show a Form to Select the widgets.
"""
permission_required = 'projector.can_see_dashboard'
template_name = 'projector/select_widgets.html'
def get_context_data(self, **kwargs):
context = super(SelectWidgetsView, self). get_context_data(**kwargs)
widgets = get_all_widgets(self.request)
activated_widgets = self.request.session.get('widgets', {})
for name, widget in widgets.items():
initial = {'widget': activated_widgets.get(name, True)}
if self.request.method == 'POST':
widget.form = SelectWidgetsForm(self.request.POST, prefix=name,
initial=initial)
else:
widget.form = SelectWidgetsForm(prefix=name, initial=initial)
context['widgets'] = widgets
return context
@transaction.commit_manually
def post(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
activated_widgets = self.request.session.get('widgets', {})
transaction.commit()
for name, widget in context['widgets'].items():
if widget.form.is_valid():
activated_widgets[name] = widget.form.cleaned_data['widget']
else:
transaction.rollback()
messages.error(request, _('Errors in the form'))
break
else:
transaction.commit()
self.request.session['widgets'] = activated_widgets
return self.render_to_response(context)
class ProjectorEdit(RedirectView):
"""
Scale or scroll the projector.
"""
permission_required = 'projector.can_manage_projector'
url = 'dashboard'
allow_ajax = True
def pre_redirect(self, request, *args, **kwargs):
direction = kwargs['direction']
if direction == 'bigger':
config['bigger'] = int(config['bigger']) + 20
elif direction == 'smaller':
config['bigger'] = int(config['bigger']) - 20
elif direction == 'up':
config['up'] = int(config['up']) - 10
elif direction == 'down':
if config['up'] < 0:
config['up'] = int(config['up']) + 10
elif direction == 'clean':
config['up'] = 0
config['bigger'] = 100
class CountdownEdit(RedirectView):
"""
Start, stop or reset the countdown.
"""
permission_required = 'projector.can_manage_projector'
url = 'dashboard'
allow_ajax = True
def pre_redirect(self, request, *args, **kwargs):
command = kwargs['command']
# countdown_state is one of 'inactive', 'paused' and 'active', 'expired'
if command in ['reset', 'start', 'stop']:
config['countdown_time'] = config['countdown_time']
if command == 'reset':
config['countdown_start_stamp'] = time()
config['countdown_pause_stamp'] = 0
config['countdown_state'] = 'inactive'
elif command == 'start':
# if we had stopped the countdown resume were we left of
if config['countdown_state'] == 'paused':
start_stamp = config['countdown_start_stamp']
pause_stamp = config['countdown_pause_stamp']
now = time()
config['countdown_start_stamp'] = now - \
(pause_stamp - start_stamp)
else:
config['countdown_start_stamp'] = time()
config['countdown_state'] = 'active'
config['countdown_pause_stamp'] = 0
elif command == 'stop':
if config['countdown_state'] == 'active':
config['countdown_pause_stamp'] = time()
config['countdown_state'] = 'paused'
elif command == 'set-default':
try:
config['countdown_time'] = \
int(self.request.GET['countdown_time'])
except ValueError:
pass
except AttributeError:
pass
def get_ajax_context(self, **kwargs):
return {
'state': config['countdown_state'],
'countdown_time': config['countdown_time'],
}
class ActivateOverlay(RedirectView):
"""
Activate or deactivate an overlay.
"""
url = 'dashboard'
allow_ajax = True
permission_required = 'projector.can_manage_projector'
@property
def overlay(self):
try:
return self._overlay
except AttributeError:
self._overlay = ProjectorOverlay.objects.get(
def_name=self.kwargs['name'])
return self._overlay
def pre_redirect(self, request, *args, **kwargs):
if kwargs['activate']:
self.overlay.active = True
else:
self.overlay.active = False
self.overlay.save()
def get_ajax_context(self, **kwargs):
return {
'active': self.overlay.active,
'def_name': self.overlay.def_name,
}
class CustomSlideCreateView(CreateView):
"""
Create a custom slide.
"""
permission_required = 'agenda.can_manage_agenda'
template_name = 'projector/new.html'
model = ProjectorSlide
context_object_name = 'customslide'
success_url = 'dashboard'
apply_url = 'customslide_edit'
class CustomSlideUpdateView(UpdateView):
"""
Update a custom slide.
"""
permission_required = 'projector.can_manage_projector'
template_name = 'projector/new.html'
model = ProjectorSlide
context_object_name = 'customslide'
success_url = 'dashboard'
apply_url = 'customslide_edit'
class CustomSlideDeleteView(DeleteView):
"""
Delete a custom slide.
"""
permission_required = 'projector.can_manage_projector'
model = ProjectorSlide
url = 'dashboard'
def register_tab(request):
"""
Register the projector tab.
"""
selected = True if request.path.startswith('/projector/') else False
return Tab(
title=_('Dashboard'),
url=reverse('dashboard'),
permission=request.user.has_perm('projector.can_manage_projector') or
request.user.has_perm('projector.can_see_dashboard'),
selected=selected,
)
def get_widgets(request):
"""
Return the widgets of the projector app
"""
widgets = []
# Projector live view widget
widgets.append(Widget(
name='live_view',
display_name=_('Projector live view'),
template='projector/live_view_widget.html',
permission_required='projector.can_see_projector',
default_column=2))
# Overlay Widget
overlays = []
for receiver, name in projector_overlays.send(sender='registerer',
register=True):
if name is not None:
try:
projector_overlay = ProjectorOverlay.objects.get(
def_name=name)
except ProjectorOverlay.DoesNotExist:
projector_overlay = ProjectorOverlay(def_name=name,
active=False)
projector_overlay.save()
overlays.append(projector_overlay)
widgets.append(Widget(
name='overlays',
display_name=_('Manage Overlays'),
template='projector/overlay_widget.html',
permission_required='projector.can_manage_projector',
default_column=2,
context={
'overlays':overlays,
'countdown_time': config['countdown_time'],
'countdown_state' : config['countdown_state']}))
# Custom slide widget
widgets.append(Widget(
name='custom_slide',
display_name=_('Custom Slide'),
template='projector/custom_slide_widget.html',
context={
'slides': ProjectorSlide.objects.all(),
'welcomepage_is_active': not bool(config["presentation"])},
permission_required='projector.can_manage_projector',
default_column=2))
return widgets