Merge branch 'master' into with-dvcs
[redakcja.git] / apps / catalogue / helpers.py
1 from functools import wraps
2
3 from django.db.models import Count
4
5
6 def active_tab(tab):
7     """
8         View decorator, which puts tab info on a request.
9     """
10     def wrapper(f):
11         @wraps(f)
12         def wrapped(request, *args, **kwargs):
13             request.catalogue_active_tab = tab
14             return f(request, *args, **kwargs)
15         return wrapped
16     return wrapper
17
18
19 class ChunksList(object):
20     def __init__(self, chunk_qs):
21         self.chunk_qs = chunk_qs.annotate(
22             book_length=Count('book__chunk')).select_related(
23             'book', 'stage__name',
24             'user')
25
26         self.book_qs = chunk_qs.values('book_id')
27
28     def __getitem__(self, key):
29         if isinstance(key, slice):
30             return self.get_slice(key)
31         elif isinstance(key, int):
32             return self.get_slice(slice(key, key+1))[0]
33         else:
34             raise TypeError('Unsupported list index. Must be a slice or an int.')
35
36     def __len__(self):
37         return self.book_qs.count()
38
39     def get_slice(self, slice_):
40         book_ids = [x['book_id'] for x in self.book_qs[slice_]]
41         chunk_qs = self.chunk_qs.filter(book__in=book_ids)
42
43         chunks_list = []
44         book = None
45         for chunk in chunk_qs:
46             if chunk.book != book:
47                 book = chunk.book
48                 chunks_list.append(ChoiceChunks(book, [chunk], chunk.book_length))
49             else:
50                 chunks_list[-1].chunks.append(chunk)
51         return chunks_list
52
53
54 class ChoiceChunks(object):
55     """
56         Associates the given chunks iterable for a book.
57     """
58
59     chunks = None
60
61     def __init__(self, book, chunks, book_length):
62         self.book = book
63         self.chunks = chunks
64         self.book_length = book_length
65