mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-11-13 01:57:00 -05:00
158 lines
6.4 KiB
Plaintext
158 lines
6.4 KiB
Plaintext
# vim:fileencoding=utf-8
|
|
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
|
from __python__ import bound_methods, hash_literals
|
|
|
|
import traceback
|
|
from elementmaker import E
|
|
from gettext import gettext as _
|
|
|
|
from ajax import encode_query_component
|
|
from book_list.item_list import build_list, create_item
|
|
from dom import ensure_id, set_css
|
|
from modals import error_dialog
|
|
from read_book.globals import current_book, runtime, ui_operations
|
|
from read_book.prefs.head_foot import format_pos
|
|
from read_book.toc import get_border_nodes, get_toc_maps
|
|
from widgets import create_button
|
|
|
|
|
|
def create_goto_list(onclick, current_position_data):
|
|
ans = E.div()
|
|
items = v'[]'
|
|
location_text = format_pos(current_position_data.progress_frac, current_position_data.book_length) + ' :: '
|
|
if current_position_data.cfi:
|
|
location_text += current_position_data.cfi
|
|
landmarks = current_book().manifest.landmarks
|
|
toc = current_book().manifest.toc
|
|
id_map = get_toc_maps(toc)[1]
|
|
before, after = get_border_nodes(toc, id_map)
|
|
if after:
|
|
items.push(create_item(_('Next section'), icon='caret-right', subtitle=after.title, action=onclick.bind(None, after.dest, after.frag)))
|
|
if before:
|
|
items.push(create_item(_('Previous section'), icon='caret-left', subtitle=before.title, action=onclick.bind(None, before.dest, before.frag)))
|
|
items.push(create_item(_('Book start'), action=onclick.bind(None, def(view): view.goto_doc_boundary(True);)))
|
|
items.push(create_item(_('Book end'), action=onclick.bind(None, def(view): view.goto_doc_boundary(False);)))
|
|
items.push(create_item(_('Metadata'), subtitle=_('Details about this book'), action=onclick.bind(None, def(view):
|
|
view.overlay.show_metadata()
|
|
)))
|
|
if not runtime.is_standalone_viewer:
|
|
items.push(create_item(_('Book page in library'), subtitle=_('The page for this book in the calibre library'), action=onclick.bind(None, def(view):
|
|
view.open_book_page()
|
|
)))
|
|
items.push(create_item(_('Location'), subtitle=location_text, action=onclick.bind(None, def(view): view.overlay.show_ask_for_location();)))
|
|
for l in landmarks:
|
|
items.push(create_item(l.title, action=onclick.bind(None, l.dest, l.frag)))
|
|
build_list(ans, items)
|
|
return ans
|
|
|
|
|
|
def get_next_section(forward):
|
|
toc = current_book().manifest.toc
|
|
id_map = get_toc_maps(toc)[1]
|
|
before, after = get_border_nodes(toc, id_map)
|
|
return after if forward else before
|
|
|
|
|
|
def create_goto_panel(current_position_data, book, container, onclick):
|
|
panel = create_goto_list(onclick, current_position_data)
|
|
set_css(container, display='flex', flex_direction='column')
|
|
set_css(panel, flex_grow='10')
|
|
container.appendChild(panel)
|
|
|
|
|
|
def create_location_overlay(current_position_data, book, overlay, container):
|
|
container_id = ensure_id(container)
|
|
container.appendChild(E.div(style='margin: 0 1rem'))
|
|
container = container.lastChild
|
|
current_cfi = current_position_data.cfi
|
|
calibre_book_url = book?.calibre_book_url
|
|
|
|
def copy_button(text_to_copy):
|
|
return create_button(_('Copy'), action=def():
|
|
src = document.querySelector(f'#{container_id} input')
|
|
orig = src.value
|
|
src.value = text_to_copy
|
|
src.focus()
|
|
src.select()
|
|
try:
|
|
document.execCommand('copy')
|
|
finally:
|
|
src.value = orig
|
|
)
|
|
|
|
def display_and_copy(label, text):
|
|
container.appendChild(E.div(
|
|
style='margin: 1rem; margin-bottom: calc(1rem - 1ex); display: flex; align-items: baseline; flex-wrap: wrap',
|
|
E.div(style='flex-grow: 10; text-overflow: ellipsis; margin-bottom: 1ex',
|
|
label, ' ', E.span(text, style='font-size: smaller; font-family: monospace')),
|
|
copy_button(text)
|
|
))
|
|
|
|
if current_cfi:
|
|
display_and_copy(_('Current location:'), current_cfi)
|
|
|
|
def goto_cfi(cfi):
|
|
if ui_operations.goto_cfi(cfi):
|
|
overlay.hide()
|
|
else:
|
|
error_dialog(_('No such location'), _(
|
|
'No location {} found').format(cfi))
|
|
|
|
def goto_ref(ref):
|
|
ref = ref.replace(/,/g, '.')
|
|
if ui_operations.goto_reference(ref):
|
|
overlay.hide()
|
|
else:
|
|
error_dialog(_('No such reference'), _(
|
|
'No reference {} found').format(ref))
|
|
|
|
if current_position_data.book_length > 0:
|
|
container.appendChild(
|
|
E.div(style='margin: 1rem', _('Current position: {}').format(
|
|
format_pos(current_position_data.progress_frac, current_position_data.book_length))))
|
|
|
|
container.appendChild(
|
|
E.div(style='margin: 1rem', _(
|
|
'Type the position, location or reference below. For a reference type ref: followed by the reference:')))
|
|
|
|
def goto_pos():
|
|
src = document.querySelector(f'#{container_id} [name=newpos]').value
|
|
if not src:
|
|
return
|
|
if src.indexOf('epubcfi(') is 0:
|
|
return goto_cfi(src)
|
|
if src.indexOf('ref:') is 0:
|
|
return goto_ref(src[len('ref:'):])
|
|
try:
|
|
ui_operations.goto_book_position(float(src))
|
|
except:
|
|
error_dialog(_('Not a valid book position'), _(
|
|
'{} is not a valid book position').format(src), traceback.format_exc())
|
|
else:
|
|
overlay.hide()
|
|
|
|
container.appendChild(E.div(
|
|
style='margin: 1rem;',
|
|
E.div(
|
|
style='display: flex; align-items: baseline; flex-wrap: wrap',
|
|
E.label(_('Go to:'), style='margin-right: 1rem'),
|
|
E.input(name='newpos', type='text', min='0', max=str(current_position_data.book_length), step='0.1', style='flex-grow: 10; margin-right: 1rem', onkeydown=def(ev):
|
|
if ev.key is 'Enter':
|
|
goto_pos()
|
|
), E.span(' '),
|
|
create_button(_('Go'), action=goto_pos)
|
|
)
|
|
))
|
|
|
|
if calibre_book_url:
|
|
if current_cfi:
|
|
calibre_book_url += '?open_at=' + encode_query_component(current_cfi)
|
|
display_and_copy(_('URL for this position:'), calibre_book_url)
|
|
elif not runtime.is_standalone_viewer:
|
|
display_and_copy(_('URL for this position:'), window.top.location.toString())
|
|
window.setTimeout(def():
|
|
container = document.getElementById(container_id)
|
|
if container:
|
|
container.querySelector('[name=newpos]').focus()
|
|
, 10)
|