From: Guillaume Pellerin Date: Thu, 21 May 2015 15:58:29 +0000 (+0200) Subject: rearrange epub objects X-Git-Tag: 1.6a~4^2~62 X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=6d8571da68fd8ceb6f9156fa1e9999ccb6ece2a3;p=telemeta.git rearrange epub objects --- diff --git a/telemeta/static/telemeta/css/telemeta_epub.css b/telemeta/static/telemeta/css/telemeta_epub.css index c3fb4e57..80304b4d 100644 --- a/telemeta/static/telemeta/css/telemeta_epub.css +++ b/telemeta/static/telemeta/css/telemeta_epub.css @@ -6,18 +6,24 @@ body { h2 { text-align: left; + font-size: 1.5em; text-transform: uppercase; font-weight: 200; } - h3 { text-align: left; - font-size: 0.8em; + font-size: 1.25em; margin-top: 0px; font-weight: normal; } +p { + text-align: left; + font-size: 0.9em; + margin-top: 0px; + font-weight: normal; +} ol { list-style-type: none; @@ -27,28 +33,22 @@ ol > li:first-child { margin-top: 0.3em; } - nav[epub|type~='toc'] > ol > li > ol { list-style-type:square; } - nav[epub|type~='toc'] > ol > li > ol > li { margin-top: 0.3em; } .item { - page-break-before: always; + page-break-after: always; } .item-image { text-align: center; } -.item-audio{ - page-break-after: avoid; -} - .item-player { width: 100%; } diff --git a/telemeta/templates/telemeta/collection_epub_urls.html b/telemeta/templates/telemeta/collection_epub_urls.html deleted file mode 100644 index 0fa92b5f..00000000 --- a/telemeta/templates/telemeta/collection_epub_urls.html +++ /dev/null @@ -1,8 +0,0 @@ - -{% for item in collection.items.all %} -

- {{ item.title }} -
-

-{% endfor %} diff --git a/telemeta/templates/telemeta/inc/collection_epub.html b/telemeta/templates/telemeta/inc/collection_epub.html deleted file mode 100644 index 37020245..00000000 --- a/telemeta/templates/telemeta/inc/collection_epub.html +++ /dev/null @@ -1,24 +0,0 @@ - - -

{{ collection.title }}

- -{% for item in items %} -
-

- Son {{ item.old_code }} : {{ item.title }}. {{ item.comment }} ({{ item.track }}) -

- -
- -
- - {% for image in item.related.all %} - {% if 'image' in image.mime_type %} -
- -
- {% endif %} - {% endfor %} - -
-{% endfor %} diff --git a/telemeta/templates/telemeta/inc/epub_collection.html b/telemeta/templates/telemeta/inc/epub_collection.html new file mode 100644 index 00000000..8df56cac --- /dev/null +++ b/telemeta/templates/telemeta/inc/epub_collection.html @@ -0,0 +1,25 @@ + + +

{{ title }}

+

{{ subtitle }}

+ +{% for item in items %} +
+

+ Son {{ item.old_code }} : {{ item.title }}. {{ item.comment }} ({{ item.track }}) +

+ +
+ +
+ + {% for image in item.related.all %} + {% if 'image' in image.mime_type %} +
+ +
+ {% endif %} + {% endfor %} + +
+{% endfor %} diff --git a/telemeta/templates/telemeta/inc/epub_preamble.html b/telemeta/templates/telemeta/inc/epub_preamble.html new file mode 100644 index 00000000..d901b11c --- /dev/null +++ b/telemeta/templates/telemeta/inc/epub_preamble.html @@ -0,0 +1,24 @@ +{% load telemeta_utils %} +{% load i18n %} + + + +

{% trans 'Preamble' %}

+ +

Cet AudioBook est destiné à la lecture des sons présenté dans le livre "Écoute musicale et acoustique" de Michèle Castellengo édité aux éditions Eyrolles.

+ +

+Conception et réalisation: Eyrolles / Parisson +

+ +

+Copyright (C) 2015 Michèle Castellengo
+Édition (E) 2015 Eyrolles
+Publication (P) 2015 Parisson
+

+ + diff --git a/telemeta/urls.py b/telemeta/urls.py index e26ae610..59e18d06 100644 --- a/telemeta/urls.py +++ b/telemeta/urls.py @@ -40,9 +40,6 @@ from django.views.generic.base import RedirectView from django.views.generic.list import ListView from telemeta.models import MediaItem, MediaCollection, MediaItemMarker, MediaCorpus, MediaFonds from telemeta.views import * -#from telemeta.views import HomeView, AdminView, CollectionView, ItemView, \ -# InstrumentView, InstrumentAliasView, PlaylistView, ProfileView, GeoView, \ -# LastestRevisionsFeed, ResourceView, UserRevisionsFeed, CollectionPackageView from jsonrpc import jsonrpc_site import os.path import telemeta.config diff --git a/telemeta/views/__init__.py b/telemeta/views/__init__.py index 4a57ae37..81519b5a 100644 --- a/telemeta/views/__init__.py +++ b/telemeta/views/__init__.py @@ -43,4 +43,5 @@ from telemeta.views.playlist import * from telemeta.views.profile import * from telemeta.views.feed import * from telemeta.views.resource import * +from telemeta.views.epub import * diff --git a/telemeta/views/collection.py b/telemeta/views/collection.py index 9e47888b..614e0a7b 100644 --- a/telemeta/views/collection.py +++ b/telemeta/views/collection.py @@ -372,24 +372,3 @@ class CollectionCopyView(CollectionAddView): return super(CollectionCopyView, self).dispatch(*args, **kwargs) -class CollectionEpubView(BaseEpubMixin, View): - "Download collection data embedded in an EPUB3 file" - - model = MediaCollection - - def get_object(self): - return MediaCollection.objects.get(public_id=self.kwargs['public_id']) - - def get(self, request, *args, **kwargs): - collection = self.get_object() - corpus = collection.corpus.all()[0] - self.write_book(corpus, collection=collection) - epub_file = open(self.path, 'rb') - response = HttpResponse(epub_file.read(), content_type='application/epub+zip') - response['Content-Disposition'] = "attachment; filename=%s" % self.filename + '.epub' - return response - - @method_decorator(login_required) - def dispatch(self, *args, **kwargs): - return super(CollectionEpubView, self).dispatch(*args, **kwargs) - diff --git a/telemeta/views/core.py b/telemeta/views/core.py index 9544be1f..ef682f22 100644 --- a/telemeta/views/core.py +++ b/telemeta/views/core.py @@ -305,102 +305,8 @@ def get_kwargs_or_none(key, kwargs): return None -class BaseEpubMixin(TelemetaBaseMixin): - "Download corpus data embedded in an EPUB3 file" - - abstract = True - local_path = os.path.dirname(__file__) - css = os.sep.join([local_path, '..', 'static', 'telemeta', 'css', 'telemeta_epub.css']) - template = os.sep.join([local_path, '..', 'templates', 'telemeta', 'inc', 'collection_epub.html']) - - def write_book(self, corpus, collection=None, path=None): - from collections import OrderedDict - from ebooklib import epub - from django.template.loader import render_to_string - - self.book = epub.EpubBook() - self.corpus = corpus - site = Site.objects.get_current() - self.chapters = [] - - if not collection: - self.filename = self.corpus.code - self.book.set_title(corpus.title) - else: - self.filename = collection.code - self.book.set_title(corpus.title + ' - ' + collection.title) - - self.path = self.cache_data.dir + os.sep + self.filename + '.epub' - - # add metadata - self.book.set_identifier(corpus.public_id) - #self.book.set_title(corpus.title + ' - ' + collection.title) - self.book.set_language('fr') - self.book.add_author(corpus.descriptions) - - # add cover image - for media in self.corpus.related.all(): - if 'cover' in media.title or 'Cover' in media.title: - self.book.set_cover("cover.png", open(media.file.path, 'r').read()) - break - - if collection: - self.collections = [collection] - else: - self.collections = self.corpus.children.all() - - for collection in self.collections: - items = {} - for item in collection.items.all(): - if '.' in item.old_code: - id = item.old_code.split('.')[1] - else: - id = item.old_code - for c in id: - if c.isalpha(): - id = id.replace(c, '.' + str(ord(c)-96)) - items[item] = float(id) - items = OrderedDict(sorted(items.items(), key=lambda t: t[1])) - - for item in items: - if item.file: - audio = open(item.file.path, 'r') - filename = str(item.file) - epub_item = epub.EpubItem(file_name=str(item.file), content=audio.read()) - self.book.add_item(epub_item) - for related in item.related.all(): - if 'image' in related.mime_type: - image = open(related.file.path, 'r') - epub_item = epub.EpubItem(file_name=str(related.file), content=image.read()) - self.book.add_item(epub_item) - context = {'collection': collection, 'site': site, 'items': items} - c = epub.EpubHtml(title=collection.title, file_name=collection.code + '.xhtml', lang='fr') - c.content = render_to_string(self.template, context) - self.chapters.append(c) - # add self.chapters to the self.book - self.book.add_item(c) - - # create table of contents - # - add manual link - # - add section - # - add auto created links to chaptersfesse - - self.book.toc = (( self.chapters )) - - # add navigation files - self.book.add_item(epub.EpubNcx()) - self.book.add_item(epub.EpubNav()) - - # add css style - style = open(self.css, 'r') - nav_css = epub.EpubItem(uid="style_nav", file_name="style/nav.css", media_type="text/css", content=style.read()) - self.book.add_item(nav_css) - - # create spin, add cover page as first page - self.chapters.insert(0,'nav') - self.chapters.insert(0,'cover') - self.book.spine = self.chapters - - # write epub file - epub.write_epub(self.path, self.book, {}) - +def cleanup_path(path): + new_path = [] + for dir in path.split(os.sep): + new_path.append(slugify(dir)) + return os.sep.join(new_path) diff --git a/telemeta/views/epub.py b/telemeta/views/epub.py new file mode 100644 index 00000000..bf64c0ba --- /dev/null +++ b/telemeta/views/epub.py @@ -0,0 +1,203 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2015 Parisson SARL + +# This software is a computer program whose purpose is to backup, analyse, +# transcode and stream any audio content with its metadata over a web frontend. + +# This software is governed by the CeCILL license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". + +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. + +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. + +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL license and that you accept its terms. + +# Authors: Guillaume Pellerin + + +from telemeta.views.core import * +from telemeta.models import * +from collections import OrderedDict +from ebooklib import epub +from django.template.loader import render_to_string + + +class BaseEpubMixin(TelemetaBaseMixin): + "Download corpus data embedded in an EPUB3 file" + + local_path = os.path.dirname(__file__) + css = os.sep.join([local_path, '..', 'static', 'telemeta', 'css', 'telemeta_epub.css']) + template = os.sep.join([local_path, '..', 'templates', 'telemeta', 'inc', 'epub_collection.html']) + template_preamble = os.sep.join([local_path, '..', 'templates', 'telemeta', 'inc', 'epub_preamble.html']) + + def write_book(self, corpus, collection=None, path=None): + self.book = epub.EpubBook() + self.corpus = corpus + site = Site.objects.get_current() + self.chapters = [] + + if not collection: + self.filename = self.corpus.code + self.book.set_title(corpus.title) + else: + self.filename = collection.code + self.book.set_title(corpus.title + ' - ' + collection.title) + + self.path = self.cache_data.dir + os.sep + self.filename + '.epub' + + # add metadata + self.book.set_identifier(corpus.public_id) + #self.book.set_title(corpus.title + ' - ' + collection.title) + self.book.set_language('fr') + self.book.add_author(corpus.descriptions) + + # add css style + style = open(self.css, 'r') + css = epub.EpubItem(uid="style_nav", file_name="style/epub.css", media_type="text/css", content=style.read()) + self.book.add_item(css) + + # add cover image + for media in self.corpus.related.all(): + if 'cover' in media.title or 'Cover' in media.title: + filename = os.path.split(media.file.path)[-1] + self.book.set_cover(filename, open(media.file.path, 'r').read()) + break + + context = {} + preamble = epub.EpubHtml(title='Preamble', file_name='preamble' + '.xhtml', lang='fr') + preamble.content = render_to_string(self.template_preamble, context) + self.book.add_item(preamble) + self.chapters.append(preamble) + + if collection: + self.collections = [collection] + mode_single = True + else: + self.collections = self.corpus.children.all() + mode_single = False + + for collection in self.collections: + items = {} + for item in collection.items.all(): + if '.' in item.old_code: + id = item.old_code.split('.')[1] + else: + id = item.old_code + for c in id: + if c.isalpha(): + id = id.replace(c, '.' + str(ord(c)-96)) + items[item] = float(id) + items = OrderedDict(sorted(items.items(), key=lambda t: t[1])) + + for item in items: + if item.file: + audio = open(item.file.path, 'r') + filename = str(item.file) + epub_item = epub.EpubItem(file_name=str(item.file), content=audio.read()) + self.book.add_item(epub_item) + for related in item.related.all(): + if 'image' in related.mime_type: + image = open(related.file.path, 'r') + epub_item = epub.EpubItem(file_name=str(related.file), content=image.read()) + self.book.add_item(epub_item) + + title_split = collection.title.split(' - ') + if len(title_split) > 1: + if '0' in title_split[0]: + title = title_split[1] + subtitle = '' + else: + title = title_split[0] + subtitle = title_split[1] + else: + title = collection.title + subtitle = '' + + context = {'collection': collection, 'title': title, 'subtitle': subtitle, + 'site': site, 'items': items} + c = epub.EpubHtml(title=' - '.join([title, subtitle]), file_name=collection.code + '.xhtml', lang='fr') + c.content = render_to_string(self.template, context) + self.chapters.append(c) + # add self.chapters to the self.book + self.book.add_item(c) + + # create table of contents + # - add manual link + # - add section + # - add auto created links to chapters + self.book.toc = (( self.chapters )) + + # add navigation files + self.book.add_item(epub.EpubNcx()) + if not mode_single: + self.book.add_item(epub.EpubNav()) + self.chapters.insert(0,'nav') + + # create spin, add cover page as first page + self.chapters.insert(0,'cover') + self.book.spine = self.chapters + + # write epub file + epub.write_epub(self.path, self.book, {}) + + +class CorpusEpubView(BaseEpubMixin, View): + "Download corpus data embedded in an EPUB3 file" + + model = MediaCorpus + + def get_object(self): + return MediaCorpus.objects.get(public_id=self.kwargs['public_id']) + + def get(self, request, *args, **kwargs): + self.write_book(self.get_object()) + epub_file = open(self.path, 'rb') + response = HttpResponse(epub_file.read(), content_type='application/epub+zip') + response['Content-Disposition'] = "attachment; filename=%s" % self.filename + '.epub' + return response + + @method_decorator(login_required) + def dispatch(self, *args, **kwargs): + return super(CorpusEpubView, self).dispatch(*args, **kwargs) + + + +class CollectionEpubView(BaseEpubMixin, View): + "Download collection data embedded in an EPUB3 file" + + model = MediaCollection + + def get_object(self): + return MediaCollection.objects.get(public_id=self.kwargs['public_id']) + + def get(self, request, *args, **kwargs): + collection = self.get_object() + corpus = collection.corpus.all()[0] + self.write_book(corpus, collection=collection) + epub_file = open(self.path, 'rb') + response = HttpResponse(epub_file.read(), content_type='application/epub+zip') + response['Content-Disposition'] = "attachment; filename=%s" % self.filename + '.epub' + return response + + @method_decorator(login_required) + def dispatch(self, *args, **kwargs): + return super(CollectionEpubView, self).dispatch(*args, **kwargs) + diff --git a/telemeta/views/resource.py b/telemeta/views/resource.py index 20bb43ce..8cefcea7 100644 --- a/telemeta/views/resource.py +++ b/telemeta/views/resource.py @@ -342,30 +342,3 @@ class ResourceEditView(ResourceSingleMixin, UpdateWithInlinesView): def dispatch(self, *args, **kwargs): return super(ResourceEditView, self).dispatch(*args, **kwargs) - -def cleanup_path(path): - new_path = [] - for dir in path.split(os.sep): - new_path.append(slugify(dir)) - return os.sep.join(new_path) - - -class CorpusEpubView(BaseEpubMixin, View): - "Download corpus data embedded in an EPUB3 file" - - model = MediaCorpus - - def get_object(self): - return MediaCorpus.objects.get(public_id=self.kwargs['public_id']) - - def get(self, request, *args, **kwargs): - self.write_book(self.get_object()) - epub_file = open(self.path, 'rb') - response = HttpResponse(epub_file.read(), content_type='application/epub+zip') - response['Content-Disposition'] = "attachment; filename=%s" % self.filename + '.epub' - return response - - @method_decorator(login_required) - def dispatch(self, *args, **kwargs): - return super(CorpusEpubView, self).dispatch(*args, **kwargs) -