mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
More work on in-server conversion
This commit is contained in:
parent
04f82a64e0
commit
4dd9a58262
@ -320,3 +320,25 @@ OPTIONS = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
OPTIONS['output']['txtz'] = OPTIONS['output']['txt']
|
OPTIONS['output']['txtz'] = OPTIONS['output']['txt']
|
||||||
|
|
||||||
|
|
||||||
|
def options_for_input_fmt(fmt):
|
||||||
|
from calibre.customize.ui import plugin_for_input_format
|
||||||
|
fmt = fmt.lower()
|
||||||
|
plugin = plugin_for_input_format(fmt)
|
||||||
|
if plugin is None:
|
||||||
|
return None, ()
|
||||||
|
full_name = plugin.name.lower().replace(' ', '_')
|
||||||
|
name = full_name.rpartition('_')[0]
|
||||||
|
return full_name, OPTIONS['input'].get(name, ())
|
||||||
|
|
||||||
|
|
||||||
|
def options_for_output_fmt(fmt):
|
||||||
|
from calibre.customize.ui import plugin_for_output_format
|
||||||
|
fmt = fmt.lower()
|
||||||
|
plugin = plugin_for_output_format(fmt)
|
||||||
|
if plugin is None:
|
||||||
|
return None, ()
|
||||||
|
full_name = plugin.name.lower().replace(' ', '_')
|
||||||
|
name = full_name.rpartition('_')[0]
|
||||||
|
return full_name, OPTIONS['output'].get(name, ())
|
||||||
|
@ -137,23 +137,35 @@ def conversion_status(ctx, rd, job_id):
|
|||||||
|
|
||||||
def get_conversion_options(input_fmt, output_fmt, book_id, db):
|
def get_conversion_options(input_fmt, output_fmt, book_id, db):
|
||||||
from calibre.ebooks.conversion.plumber import create_dummy_plumber
|
from calibre.ebooks.conversion.plumber import create_dummy_plumber
|
||||||
from calibre.ebooks.conversion.config import load_specifics, load_defaults, OPTIONS
|
from calibre.ebooks.conversion.config import (
|
||||||
|
load_specifics, load_defaults, OPTIONS, options_for_input_fmt, options_for_output_fmt)
|
||||||
from calibre.customize.conversion import OptionRecommendation
|
from calibre.customize.conversion import OptionRecommendation
|
||||||
plumber = create_dummy_plumber(input_fmt, output_fmt)
|
plumber = create_dummy_plumber(input_fmt, output_fmt)
|
||||||
specifics = load_specifics(db, book_id)
|
specifics = load_specifics(db, book_id)
|
||||||
ans = {'options': {}, 'disabled': set()}
|
ans = {'options': {}, 'disabled': set()}
|
||||||
for group_name, option_names in OPTIONS['pipe'].iteritems():
|
|
||||||
if group_name == 'debug':
|
def merge_group(group_name, option_names):
|
||||||
continue
|
if not group_name or group_name == 'debug':
|
||||||
|
return
|
||||||
defs = load_defaults(group_name)
|
defs = load_defaults(group_name)
|
||||||
defs.merge_recommendations(plumber.get_option, OptionRecommendation.LOW, option_names)
|
defs.merge_recommendations(plumber.get_option_by_name, OptionRecommendation.LOW, option_names)
|
||||||
specifics.merge_recommendations(plumber.get_option, OptionRecommendation.HIGH, option_names, only_existing=True)
|
specifics.merge_recommendations(plumber.get_option_by_name, OptionRecommendation.HIGH, option_names, only_existing=True)
|
||||||
for k in defs:
|
for k in defs:
|
||||||
if k in specifics:
|
if k in specifics:
|
||||||
defs[k] = specifics[k]
|
defs[k] = specifics[k]
|
||||||
defs = defs.as_dict()
|
defs = defs.as_dict()
|
||||||
ans['options'].update(defs['options'])
|
ans['options'].update(defs['options'])
|
||||||
ans['disabled'] |= defs['disabled']
|
ans['disabled'] |= set(defs['disabled'])
|
||||||
|
|
||||||
|
for group_name, option_names in OPTIONS['pipe'].iteritems():
|
||||||
|
merge_group(group_name, option_names)
|
||||||
|
|
||||||
|
group_name, option_names = options_for_input_fmt(input_fmt)
|
||||||
|
merge_group(group_name, option_names)
|
||||||
|
group_name, option_names = options_for_output_fmt(output_fmt)
|
||||||
|
merge_group(group_name, option_names)
|
||||||
|
|
||||||
|
ans['disabled'] = tuple(ans['disabled'])
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,11 +11,14 @@ from book_list.library_data import load_status, url_books_query
|
|||||||
from book_list.router import back, report_a_load_failure
|
from book_list.router import back, report_a_load_failure
|
||||||
from book_list.top_bar import create_top_bar, set_title
|
from book_list.top_bar import create_top_bar, set_title
|
||||||
from book_list.ui import set_panel_handler
|
from book_list.ui import set_panel_handler
|
||||||
from dom import add_extra_css, build_rule, clear, ensure_id
|
from dom import add_extra_css, build_rule
|
||||||
from utils import conditional_timeout, parse_url_params
|
from utils import conditional_timeout, parse_url_params
|
||||||
from widgets import create_button
|
from widgets import create_button
|
||||||
|
|
||||||
CLASS_NAME = 'convert-book-panel'
|
CLASS_NAME = 'convert-book-panel'
|
||||||
|
current_state = 'initializing'
|
||||||
|
overall_container_id = None
|
||||||
|
initializers = {}
|
||||||
|
|
||||||
add_extra_css(def():
|
add_extra_css(def():
|
||||||
sel = '.' + CLASS_NAME + ' '
|
sel = '.' + CLASS_NAME + ' '
|
||||||
@ -28,12 +31,18 @@ conversion_data = None
|
|||||||
conversion_data_load_status = {'loading':True, 'ok':False, 'error_html':None, 'current_fetch':None}
|
conversion_data_load_status = {'loading':True, 'ok':False, 'error_html':None, 'current_fetch':None}
|
||||||
|
|
||||||
|
|
||||||
|
def container_for_current_state():
|
||||||
|
ans = document.getElementById(overall_container_id)
|
||||||
|
if ans:
|
||||||
|
return ans.querySelector(f'[data-state="{current_state}"]')
|
||||||
|
|
||||||
|
|
||||||
def on_conversion_started(end_type, xhr, ev):
|
def on_conversion_started(end_type, xhr, ev):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def get_conversion_options(container):
|
def get_conversion_options(container):
|
||||||
return conversion_data.conversion_options
|
return conversion_data.conversion_options.options
|
||||||
|
|
||||||
|
|
||||||
def start_conversion():
|
def start_conversion():
|
||||||
@ -48,17 +57,13 @@ def start_conversion():
|
|||||||
ajax_send(f'/conversion/start/{conversion_data.book_id}', data, on_conversion_started, query=query)
|
ajax_send(f'/conversion/start/{conversion_data.book_id}', data, on_conversion_started, query=query)
|
||||||
|
|
||||||
|
|
||||||
def create_convert_book(container):
|
def create_configuring_markup():
|
||||||
conversion_data.container_id = ensure_id(container)
|
ans = E.div(class_='top')
|
||||||
set_title(container.parentNode, _('Convert: {}').format(conversion_data.title))
|
|
||||||
container.appendChild(E.div(class_='top'))
|
|
||||||
|
|
||||||
def generate_choice(name):
|
def generate_choice(name):
|
||||||
formats = conversion_data[name]
|
|
||||||
ans = E.select(name=name)
|
ans = E.select(name=name)
|
||||||
for fmt in formats:
|
|
||||||
ans.appendChild(E.option(fmt, value=fmt))
|
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
tcell = 'display: table-cell; padding-top: 1em; padding-left: 1em'
|
tcell = 'display: table-cell; padding-top: 1em; padding-left: 1em'
|
||||||
|
|
||||||
start_conv = E.div(
|
start_conv = E.div(
|
||||||
@ -79,7 +84,16 @@ def create_convert_book(container):
|
|||||||
create_button(_('Start conversion'), action=start_conversion)
|
create_button(_('Start conversion'), action=start_conversion)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
container.lastChild.appendChild(start_conv)
|
ans.appendChild(start_conv)
|
||||||
|
|
||||||
|
def initialize(container):
|
||||||
|
for name in 'input_formats', 'output_formats':
|
||||||
|
sel = container.querySelector(f'select[name="{name}"]')
|
||||||
|
formats = conversion_data[name]
|
||||||
|
for fmt in formats:
|
||||||
|
sel.appendChild(E.option(fmt, value=fmt))
|
||||||
|
|
||||||
|
return ans, initialize
|
||||||
|
|
||||||
|
|
||||||
# Initialization {{{
|
# Initialization {{{
|
||||||
@ -121,28 +135,62 @@ def on_close(container_id):
|
|||||||
|
|
||||||
|
|
||||||
def check_for_data_loaded():
|
def check_for_data_loaded():
|
||||||
|
nonlocal current_state
|
||||||
container = this
|
container = this
|
||||||
if load_status.loading or conversion_data_load_status.loading:
|
if load_status.loading or conversion_data_load_status.loading:
|
||||||
conditional_timeout(container.id, 5, check_for_data_loaded)
|
conditional_timeout(container.id, 5, check_for_data_loaded)
|
||||||
return
|
return
|
||||||
container = container.lastChild
|
container = container.lastChild
|
||||||
clear(container)
|
|
||||||
if not load_status.ok:
|
if not load_status.ok:
|
||||||
report_load_failure(container)
|
current_state = 'load-failure'
|
||||||
return
|
report_load_failure(container_for_current_state())
|
||||||
if not conversion_data_load_status.ok:
|
elif not conversion_data_load_status.ok:
|
||||||
|
current_state = 'load-failure'
|
||||||
report_a_load_failure(
|
report_a_load_failure(
|
||||||
container, _('Failed to load conversion data from calibre, with error:'),
|
container_for_current_state(),
|
||||||
|
_('Failed to load conversion data from calibre, with error:'),
|
||||||
conversion_data_load_status.error_html)
|
conversion_data_load_status.error_html)
|
||||||
return
|
else:
|
||||||
create_convert_book(container)
|
set_title(container.parentNode, _('Convert: {}').format(conversion_data.title))
|
||||||
|
current_state = 'configuring'
|
||||||
|
apply_state_to_markup()
|
||||||
|
|
||||||
|
|
||||||
|
def create_markup(container):
|
||||||
|
container.appendChild(E.div(
|
||||||
|
data_state='initializing', style='margin: 1ex 1em',
|
||||||
|
E.div(_('Loading conversion data, please wait...'))
|
||||||
|
))
|
||||||
|
container.appendChild(E.div(
|
||||||
|
data_state='load-failure', style='margin: 1ex 1em',
|
||||||
|
))
|
||||||
|
|
||||||
|
ccm, init = create_configuring_markup()
|
||||||
|
ccm.dataset.state = 'configuring'
|
||||||
|
container.appendChild(ccm)
|
||||||
|
initializers[ccm.dataset.state] = init
|
||||||
|
|
||||||
|
|
||||||
|
def apply_state_to_markup():
|
||||||
|
container = document.getElementById(overall_container_id)
|
||||||
|
if container:
|
||||||
|
for node in container.lastChild.childNodes:
|
||||||
|
if node.dataset.state is current_state:
|
||||||
|
node.style.display = 'block'
|
||||||
|
if initializers[current_state]:
|
||||||
|
initializers[current_state](node)
|
||||||
|
else:
|
||||||
|
node.style.display = 'none'
|
||||||
|
|
||||||
|
|
||||||
def init(container_id):
|
def init(container_id):
|
||||||
|
nonlocal overall_container_id
|
||||||
container = document.getElementById(container_id)
|
container = document.getElementById(container_id)
|
||||||
|
overall_container_id = container_id
|
||||||
create_top_bar(container, title=_('Convert book'), action=on_close.bind(None, container_id), icon='close')
|
create_top_bar(container, title=_('Convert book'), action=on_close.bind(None, container_id), icon='close')
|
||||||
container.appendChild(E.div(class_=CLASS_NAME))
|
container.appendChild(E.div(class_=CLASS_NAME))
|
||||||
container.lastChild.appendChild(E.div(_('Loading conversion data, please wait...'), style='margin: 1ex 1em'))
|
create_markup(container.lastChild)
|
||||||
|
apply_state_to_markup()
|
||||||
conditional_timeout(container_id, 5, check_for_data_loaded)
|
conditional_timeout(container_id, 5, check_for_data_loaded)
|
||||||
q = parse_url_params()
|
q = parse_url_params()
|
||||||
fetch_conversion_data(q.book_id)
|
fetch_conversion_data(q.book_id)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user