OpenSlides/openslides/projector/api.py

211 lines
5.5 KiB
Python

from json import dumps
from time import time
from django.template.loader import render_to_string
from openslides.config.api import config
from openslides.utils.exceptions import OpenSlidesError
from .signals import projector_overlays
slide_callback = {}
"""
A dictonary where the key is the name of a slide, and the value is a
callable object which returns the html code for a slide.
"""
slide_model = {}
"""
A dictonary for SlideMixin models to reference from the slide_callback_name to
the Model
"""
# TODO: Find a bether way to do this. Maybe by reimplementing slides with
# metaclasses
class SlideError(OpenSlidesError):
pass
def call_on_projector(calls):
"""
Sends data to the projector.
The argument call has to be a dictionary with the javascript function name
as key and the argument for it as value.
"""
# TODO: remove this function
projector_js_cache = config['projector_js_cache']
projector_js_cache.update(calls)
config['projector_js_cache'] = projector_js_cache
def get_projector_content(slide_dict=None):
"""
Returns the HTML-Content block for the projector.
Slide_dict has to be an dictonary with the key 'callback'.
If slide_dict is None, use the active slide from the database.
"""
if slide_dict is None:
slide_dict = config['projector_active_slide'].copy()
callback = slide_dict.pop('callback', None)
try:
slide_content = slide_callback[callback](**slide_dict)
except (KeyError, SlideError):
slide_content = default_slide()
return slide_content
def default_slide():
"""
Returns the HTML Code for the default slide.
"""
return render_to_string('projector/default_slide.html')
def get_overlays(only_active=False):
"""
Returns all overlay objects.
If only_active is True, returns only active overlays.
The returned value is a dictonary with the name of the overlay as key, and
the overlay object as value.
"""
overlays = {}
for receiver, overlay in projector_overlays.send(sender='get_overlays'):
if not only_active or overlay.is_active():
overlays[overlay.name] = overlay
return overlays
def get_projector_overlays_js(as_json=False):
"""
Returns JS-Code for the active overlays.
The retuned value is a list of json objects.
"""
javascript = []
for overlay in get_overlays().values():
if overlay.is_active():
overlay_js = overlay.get_javascript()
if overlay_js:
if as_json:
overlay_js = dumps(overlay_js)
javascript.append(overlay_js)
return javascript
def register_slide(name, callback, model=None):
"""
Registers a function as slide callback.
The optional argument 'model' is used to register a SlideModelClass.
"""
slide_callback[name] = callback
if model is not None:
slide_model[name] = model
def register_slide_model(SlideModel, template):
"""
Shortcut for register_slide for a Model with the SlideMixin.
The Argument 'SlideModel' has to be a Django-Model-Class, which is a subclass
of SlideMixin. Template has to be a string to the path of a template.
"""
def model_slide(**kwargs):
"""
Return the html code for the model slide.
"""
slide_pk = kwargs.get('pk', None)
try:
slide = SlideModel.objects.get(pk=slide_pk)
except SlideModel.DoesNotExist:
raise SlideError
else:
context = slide.get_slide_context()
return render_to_string(template, context)
register_slide(SlideModel.slide_callback_name, model_slide, SlideModel)
def set_active_slide(callback, **kwargs):
"""
Set the active Slide.
callback: The name of the slide callback.
kwargs: Keyword arguments for the slide callback.
"""
kwargs.update(callback=callback)
config['projector_active_slide'] = kwargs
def get_active_slide():
"""
Returns the dictonary, which defines the active slide.
"""
return config['projector_active_slide']
def get_active_object():
"""
Returns an object if the active slide is an instance of SlideMixin.
In other case, returns None
"""
active_slide_dict = get_active_slide()
callback_name = active_slide_dict.get('callback', None)
object_pk = active_slide_dict.get('pk', None)
try:
Model = slide_model[callback_name]
except KeyError:
value = None
else:
try:
value = Model.objects.get(pk=object_pk)
except Model.DoesNotExist:
value = None
return value
def start_countdown():
"""
Starts the countdown
"""
# 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
def stop_countdown():
"""
Stops the countdown
"""
if config['countdown_state'] == 'active':
config['countdown_state'] = 'paused'
config['countdown_pause_stamp'] = time()
def reset_countdown():
"""
Resets the countdown
"""
config['countdown_start_stamp'] = time()
config['countdown_pause_stamp'] = 0
config['countdown_state'] = 'inactive'