mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
More work on server book conversion
This commit is contained in:
parent
27c79db06a
commit
3695c35229
@ -45,6 +45,20 @@ def load_defaults(name):
|
||||
return r
|
||||
|
||||
|
||||
def load_all_defaults():
|
||||
ans = {}
|
||||
for x in os.listdir(config_dir):
|
||||
if x.endswith('.py'):
|
||||
path = os.path.join(config_dir, x)
|
||||
with ExclusiveFile(path) as f:
|
||||
raw = f.read()
|
||||
r = GuiRecommendations()
|
||||
if raw:
|
||||
r.deserialize(raw)
|
||||
ans[os.path.splitext(x)[0]] = r.copy()
|
||||
return ans
|
||||
|
||||
|
||||
def save_specifics(db, book_id, recs):
|
||||
raw = recs.serialize()
|
||||
db.set_conversion_options(book_id, 'PIPE', raw)
|
||||
@ -146,14 +160,11 @@ def get_preferred_input_format_for_book(db, book_id):
|
||||
|
||||
|
||||
def sort_formats_by_preference(formats, prefs):
|
||||
uprefs = [x.upper() for x in prefs]
|
||||
uprefs = {x.upper():i for i, x in enumerate(prefs)}
|
||||
|
||||
def key(x):
|
||||
try:
|
||||
return uprefs.index(x.upper())
|
||||
except ValueError:
|
||||
pass
|
||||
return len(prefs)
|
||||
return uprefs.get(x.upper(), len(prefs))
|
||||
|
||||
return sorted(formats, key=key)
|
||||
|
||||
|
||||
@ -188,5 +199,16 @@ def get_output_formats(preferred_output_format):
|
||||
fmts.append(pfo)
|
||||
else:
|
||||
fmts = list(sorted(all_formats,
|
||||
key=lambda x:{'EPUB':'!A', 'MOBI':'!B'}.get(x.upper(), x)))
|
||||
key=lambda x:{'EPUB':'!A', 'AZW3':'!B', 'MOBI':'!C'}.get(x.upper(), x)))
|
||||
return fmts
|
||||
|
||||
|
||||
def get_sorted_output_formats():
|
||||
preferred_output_format = prefs['output_format'].upper()
|
||||
fmts = get_output_formats(preferred_output_format)
|
||||
try:
|
||||
fmts.remove(preferred_output_format)
|
||||
except Exception:
|
||||
pass
|
||||
fmts.insert(0, preferred_output_format)
|
||||
return fmts
|
||||
|
44
src/calibre/srv/convert.py
Normal file
44
src/calibre/srv/convert.py
Normal file
@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env python2
|
||||
# vim:fileencoding=utf-8
|
||||
# License: GPLv3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
from calibre.srv.errors import BookNotFound
|
||||
from calibre.srv.routes import endpoint, json
|
||||
from calibre.srv.utils import get_library_data
|
||||
|
||||
|
||||
def conversion_defaults():
|
||||
from calibre.ebooks.conversion.config import load_all_defaults
|
||||
ans = getattr(conversion_defaults, 'ans', None)
|
||||
if ans is None:
|
||||
ans = conversion_defaults.ans = load_all_defaults()
|
||||
return ans
|
||||
|
||||
|
||||
@endpoint('/conversion/book-data/{book_id}', postprocess=json, types={'book_id': int})
|
||||
def conversion_data(ctx, rd, book_id):
|
||||
from calibre.ebooks.conversion.config import (
|
||||
NoSupportedInputFormats, get_input_format_for_book,
|
||||
get_sorted_output_formats, load_specifics)
|
||||
db = get_library_data(ctx, rd)[0]
|
||||
if not ctx.has_id(rd, db, book_id):
|
||||
raise BookNotFound(book_id, db)
|
||||
try:
|
||||
input_format, input_formats = get_input_format_for_book(db, book_id)
|
||||
except NoSupportedInputFormats:
|
||||
input_formats = []
|
||||
else:
|
||||
if input_format in input_formats:
|
||||
input_formats.remove(input_format)
|
||||
input_formats.insert(0, input_format)
|
||||
ans = {
|
||||
'input_formats': [x.upper() for x in input_formats],
|
||||
'output_formats': get_sorted_output_formats(),
|
||||
'conversion_defaults': conversion_defaults(),
|
||||
'conversion_specifics': load_specifics(db, book_id),
|
||||
'title': db.field_for('title', book_id),
|
||||
'authors': db.field_for('authors', book_id),
|
||||
}
|
||||
return ans
|
@ -179,7 +179,7 @@ class Context(object):
|
||||
return old[1]
|
||||
|
||||
|
||||
SRV_MODULES = ('ajax', 'books', 'cdb', 'code', 'content', 'legacy', 'opds', 'users_api')
|
||||
SRV_MODULES = ('ajax', 'books', 'cdb', 'code', 'content', 'legacy', 'opds', 'users_api', 'convert')
|
||||
|
||||
|
||||
class Handler(object):
|
||||
|
@ -14,7 +14,7 @@ from book_list.library_data import (
|
||||
book_metadata, cover_url, current_library_id, current_virtual_library,
|
||||
download_url, library_data, load_status, set_book_metadata
|
||||
)
|
||||
from book_list.router import back, home, open_book
|
||||
from book_list.router import back, home, open_book, report_a_load_failure
|
||||
from book_list.theme import get_color, get_font_size
|
||||
from book_list.top_bar import add_button, clear_buttons, create_top_bar, set_title
|
||||
from book_list.ui import query_as_href, set_panel_handler, show_panel
|
||||
@ -546,17 +546,10 @@ def create_book_details(container):
|
||||
|
||||
|
||||
def report_load_failure(container):
|
||||
err = E.div()
|
||||
safe_set_inner_html(err, load_status.error_html)
|
||||
container.appendChild(E.div(
|
||||
style='margin: 1ex 1em',
|
||||
E.div(_('Failed to load books from calibre library, with error:')),
|
||||
err,
|
||||
E.div(
|
||||
style='margin-top: 1em; border-top: solid 1px currentColor; padding-top: 1ex;',
|
||||
E.a(onclick=def(): home(replace=True);, href='javascript: void(0)', style='color: blue', _('Go back to the home page')))
|
||||
),
|
||||
)
|
||||
report_a_load_failure(
|
||||
container, _('Failed to load books from calibre library, with error:'),
|
||||
load_status.error_html)
|
||||
|
||||
|
||||
|
||||
def check_for_books_loaded():
|
||||
|
89
src/pyj/book_list/convert_book.pyj
Normal file
89
src/pyj/book_list/convert_book.pyj
Normal file
@ -0,0 +1,89 @@
|
||||
# vim:fileencoding=utf-8
|
||||
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
from __python__ import bound_methods, hash_literals
|
||||
|
||||
from elementmaker import E
|
||||
from gettext import gettext as _
|
||||
|
||||
from ajax import ajax
|
||||
from book_list.book_details import report_load_failure
|
||||
from book_list.library_data import load_status, url_books_query
|
||||
from book_list.router import back, report_a_load_failure
|
||||
from book_list.top_bar import create_top_bar
|
||||
from book_list.ui import set_panel_handler
|
||||
from dom import add_extra_css, build_rule, clear
|
||||
from utils import conditional_timeout, parse_url_params
|
||||
|
||||
CLASS_NAME = 'convert-book-panel'
|
||||
|
||||
add_extra_css(def():
|
||||
sel = '.' + CLASS_NAME + ' '
|
||||
style = build_rule(sel, placeholder='TODO: add this')
|
||||
return style
|
||||
)
|
||||
|
||||
|
||||
conversion_data = None
|
||||
conversion_data_load_status = {'loading':True, 'ok':False, 'error_html':None, 'current_fetch': None}
|
||||
|
||||
|
||||
def on_data_loaded(end_type, xhr, ev):
|
||||
nonlocal conversion_data
|
||||
conversion_data_load_status.current_fetch = None
|
||||
|
||||
def bad_load(msg):
|
||||
conversion_data_load_status.ok = False
|
||||
conversion_data_load_status.loading = False
|
||||
conversion_data_load_status.error_html = msg or xhr.error_html
|
||||
|
||||
if end_type is 'load':
|
||||
conversion_data = JSON.parse(xhr.responseText)
|
||||
elif end_type is 'abort':
|
||||
pass
|
||||
else:
|
||||
bad_load()
|
||||
|
||||
|
||||
def fetch_conversion_data(book_id):
|
||||
if conversion_data_load_status.current_fetch:
|
||||
conversion_data_load_status.current_fetch.abort()
|
||||
query = url_books_query()
|
||||
conversion_data_load_status.loading = True
|
||||
conversion_data_load_status.ok = False
|
||||
conversion_data_load_status.error_html = None
|
||||
conversion_data_load_status.current_fetch = ajax(f'conversion/books-data/{book_id}', on_data_loaded, query=query)
|
||||
conversion_data_load_status.current_fetch.send()
|
||||
|
||||
|
||||
def on_close(container_id):
|
||||
back()
|
||||
|
||||
|
||||
def check_for_data_loaded():
|
||||
container = this
|
||||
if load_status.loading or conversion_data_load_status.loading:
|
||||
conditional_timeout(container.id, 5, check_for_data_loaded)
|
||||
return
|
||||
container = container.lastChild
|
||||
clear(container)
|
||||
if not load_status.ok:
|
||||
report_load_failure(container)
|
||||
return
|
||||
if not conversion_data_load_status.ok:
|
||||
report_a_load_failure(
|
||||
container, _('Failed to load conversion data from calibre, with error:'),
|
||||
conversion_data_load_status.error_html)
|
||||
# create_convert_book(container)
|
||||
|
||||
|
||||
def init(container_id):
|
||||
container = document.getElementById(container_id)
|
||||
create_top_bar(container, title=_('Convert book'), action=on_close.bind(None, container_id), icon='close')
|
||||
container.appendChild(E.div(class_=CLASS_NAME))
|
||||
container.lastChild.appendChild(E.div(_('Loading conversion data, please wait...'), style='margin: 1ex 1em'))
|
||||
conditional_timeout(container_id, 5, check_for_data_loaded)
|
||||
q = parse_url_params()
|
||||
fetch_conversion_data(q.book_id)
|
||||
|
||||
|
||||
set_panel_handler('convert_book', init)
|
@ -2,11 +2,17 @@
|
||||
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
from __python__ import bound_methods, hash_literals
|
||||
|
||||
from elementmaker import E
|
||||
from gettext import gettext as _
|
||||
|
||||
from book_list.constants import book_list_container_id, read_book_container_id
|
||||
from book_list.globals import get_current_query
|
||||
from book_list.library_data import current_library_id
|
||||
from modals import close_all_modals
|
||||
from utils import encode_query_with_path, parse_url_params, request_full_screen
|
||||
from utils import (
|
||||
encode_query_with_path, parse_url_params, request_full_screen,
|
||||
safe_set_inner_html
|
||||
)
|
||||
|
||||
mode_handlers = {}
|
||||
default_mode_handler = None
|
||||
@ -89,5 +95,20 @@ def back():
|
||||
q = {}
|
||||
push_state(q, replace=True)
|
||||
|
||||
|
||||
def home(replace=False):
|
||||
push_state({})
|
||||
|
||||
|
||||
def report_a_load_failure(container, msg, error_html):
|
||||
err = E.div()
|
||||
safe_set_inner_html(err, error_html)
|
||||
container.appendChild(E.div(
|
||||
style='margin: 1ex 1em',
|
||||
E.div(msg),
|
||||
err,
|
||||
E.div(
|
||||
style='margin-top: 1em; border-top: solid 1px currentColor; padding-top: 1ex;',
|
||||
E.a(onclick=def(): home(replace=True);, href='javascript: void(0)', style='color: blue', _('Go back to the home page')))
|
||||
),
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user