Restore reference mode from the 3.x viewer

This commit is contained in:
Kovid Goyal 2019-12-09 09:05:28 +05:30
parent d6262bbb90
commit e1d9a25f81
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 99 additions and 12 deletions

View File

@ -29,6 +29,7 @@ from read_book.paged_mode import (
scroll_by_page as paged_scroll_by_page, scroll_to_elem, scroll_by_page as paged_scroll_by_page, scroll_to_elem,
scroll_to_fraction as paged_scroll_to_fraction, snap_to_selection scroll_to_fraction as paged_scroll_to_fraction, snap_to_selection
) )
from read_book.referencing import end_reference_mode, start_reference_mode
from read_book.resources import finalize_resources, unserialize_html from read_book.resources import finalize_resources, unserialize_html
from read_book.settings import ( from read_book.settings import (
apply_colors, apply_font_size, apply_settings, apply_stylesheet, opts, apply_colors, apply_font_size, apply_settings, apply_stylesheet, opts,
@ -80,6 +81,7 @@ class IframeBoss:
def __init__(self): def __init__(self):
window.navigator.epubReadingSystem = EPUBReadingSystem() window.navigator.epubReadingSystem = EPUBReadingSystem()
self.last_cfi = None self.last_cfi = None
self.reference_mode_enabled = False
self.replace_history_on_next_cfi_update = True self.replace_history_on_next_cfi_update = True
self.blob_url_map = {} self.blob_url_map = {}
self.content_ready = False self.content_ready = False
@ -100,6 +102,7 @@ class IframeBoss:
'window_size': self.received_window_size, 'window_size': self.received_window_size,
'get_current_cfi': self.get_current_cfi, 'get_current_cfi': self.get_current_cfi,
'set_forward_keypresses': self.set_forward_keypresses, 'set_forward_keypresses': self.set_forward_keypresses,
'set_reference_mode': self.set_reference_mode,
} }
self.comm = IframeClient(handlers) self.comm = IframeClient(handlers)
self.last_window_ypos = 0 self.last_window_ypos = 0
@ -155,6 +158,7 @@ class IframeBoss:
self.content_ready = False self.content_ready = False
self.replace_history_on_next_cfi_update = True self.replace_history_on_next_cfi_update = True
self.book = current_book.book = data.book self.book = current_book.book = data.book
self.reference_mode_enabled = data.reference_mode_enabled
self.is_titlepage = data.is_titlepage self.is_titlepage = data.is_titlepage
spine = self.book.manifest.spine spine = self.book.manifest.spine
index = spine.indexOf(data.name) index = spine.indexOf(data.name)
@ -178,7 +182,13 @@ class IframeBoss:
self.anchor_funcs = paged_anchor_funcs self.anchor_funcs = paged_anchor_funcs
update_settings(data.settings) update_settings(data.settings)
self.keyboard_shortcut_map = create_shortcut_map(data.settings.keyboard_shortcuts) self.keyboard_shortcut_map = create_shortcut_map(data.settings.keyboard_shortcuts)
set_current_spine_item({'name':data.name, 'is_first':index is 0, 'is_last':index is spine.length - 1, 'initial_position':data.initial_position}) set_current_spine_item({
'name':data.name,
'is_first':index is 0,
'is_last':index is spine.length - 1,
'index': index,
'initial_position':data.initial_position
})
self.last_cfi = None self.last_cfi = None
for name in self.blob_url_map: for name in self.blob_url_map:
window.URL.revokeObjectURL(self.blob_url_map[name]) window.URL.revokeObjectURL(self.blob_url_map[name])
@ -239,6 +249,8 @@ class IframeBoss:
if self.is_titlepage and not opts.cover_preserve_aspect_ratio: if self.is_titlepage and not opts.cover_preserve_aspect_ratio:
document.body.classList.add('cover-fill') document.body.classList.add('cover-fill')
document.body.classList.add(f'calibre-viewer-{layout_style()}') document.body.classList.add(f'calibre-viewer-{layout_style()}')
if self.reference_mode_enabled:
start_reference_mode()
self.last_window_width, self.last_window_height = scroll_viewport.width(), scroll_viewport.height() self.last_window_width, self.last_window_height = scroll_viewport.width(), scroll_viewport.height()
apply_settings() apply_settings()
fix_fullscreen_svg_images() fix_fullscreen_svg_images()
@ -269,8 +281,7 @@ class IframeBoss:
self.find(ipos.search_data, True) self.find(ipos.search_data, True)
spine = self.book.manifest.spine spine = self.book.manifest.spine
files = self.book.manifest.files files = self.book.manifest.files
current_name = current_spine_item().name spine_index = csi.index
spine_index = spine.indexOf(current_name)
self.length_before = 0 self.length_before = 0
if spine_index > -1: if spine_index > -1:
for i in range(spine_index): for i in range(spine_index):
@ -297,9 +308,7 @@ class IframeBoss:
cfi = current_cfi() cfi = current_cfi()
selected_text = window.getSelection().toString() selected_text = window.getSelection().toString()
if cfi: if cfi:
spine = self.book.manifest.spine index = current_spine_item().index
current_name = current_spine_item().name
index = spine.indexOf(current_name)
if index > -1: if index > -1:
cfi = 'epubcfi(/{}{})'.format(2*(index+1), cfi) cfi = 'epubcfi(/{}{})'.format(2*(index+1), cfi)
self.send_message( self.send_message(
@ -312,9 +321,7 @@ class IframeBoss:
def update_cfi(self): def update_cfi(self):
cfi = current_cfi() cfi = current_cfi()
if cfi: if cfi:
spine = self.book.manifest.spine index = current_spine_item().index
current_name = current_spine_item().name
index = spine.indexOf(current_name)
if index > -1: if index > -1:
cfi = 'epubcfi(/{}{})'.format(2*(index+1), cfi) cfi = 'epubcfi(/{}{})'.format(2*(index+1), cfi)
pf = self.calculate_progress_frac() pf = self.calculate_progress_frac()
@ -472,6 +479,16 @@ class IframeBoss:
else: else:
self.send_message('find_in_spine', text=data.text, backwards=data.backwards, searched_in_spine=data.searched_in_spine) self.send_message('find_in_spine', text=data.text, backwards=data.backwards, searched_in_spine=data.searched_in_spine)
def reference_item_changed(self, ref_num_or_none):
self.send_message('reference_item_changed', refnum=ref_num_or_none, index=current_spine_item().index)
def set_reference_mode(self, data):
self.reference_mode_enabled = data.enabled
if data.enabled:
start_reference_mode()
else:
end_reference_mode()
def main(): def main():
main.boss = IframeBoss() main.boss = IframeBoss()

View File

@ -0,0 +1,35 @@
# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2019, Kovid Goyal <kovid at kovidgoyal.net>
# noqa: eol-semicolon
from __python__ import bound_methods, hash_literals
from read_book.globals import get_boss
def on_mouse_over(ev):
p = this
if p.dataset.calibreRefNum:
refnum = int(p.dataset.calibreRefNum)
get_boss().reference_item_changed(refnum)
def on_mouse_out(ev):
get_boss().reference_item_changed(None)
def start_reference_mode():
i = 0
for p in document.getElementsByTagName('p'):
i += 1
if not p.dataset.calibreRefNum:
p.dataset.calibreRefNum = i + ''
p.addEventListener('mouseover', on_mouse_over, {'passive': True})
p.addEventListener('mouseout', on_mouse_out, {'passive': True})
def end_reference_mode():
for p in document.getElementsByTagName('p'):
if p.dataset.calibreRefNum:
p.removeEventListener('mouseover', on_mouse_over, {'passive': True})
p.removeEventListener('mouseout', on_mouse_out, {'passive': True})
v'delete p.dataset.calibreRefNum'

View File

@ -228,6 +228,12 @@ def shortcuts_definition():
_('Toggle between Paged mode and Flow mode for text layout') _('Toggle between Paged mode and Flow mode for text layout')
), ),
'toggle_reference_mode': desc(
'Ctrl+x',
'ui',
_('Toggle the Reference mode')
),
'reload_book': desc( 'reload_book': desc(
v"['F5', 'Ctrl+r']", v"['F5', 'Ctrl+r']",
'ui', 'ui',

View File

@ -147,6 +147,7 @@ class View:
def __init__(self, container): def __init__(self, container):
self.timers = Timers() self.timers = Timers()
self.reference_mode_enabled = False
self.loaded_resources = {} self.loaded_resources = {}
self.current_progress_frac = self.current_file_progress_frac = 0 self.current_progress_frac = self.current_file_progress_frac = 0
self.current_toc_node = self.current_toc_toplevel_node = None self.current_toc_node = self.current_toc_toplevel_node = None
@ -190,8 +191,13 @@ class View:
E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; overflow: auto; display:none', id='book-overlay'), # main overlay E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; overflow: auto; display:none', id='book-overlay'), # main overlay
E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; display:none', id='controls-help-overlay'), # controls help overlay E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; display:none', id='controls-help-overlay'), # controls help overlay
) )
) ),
) E.div(
style=f'color: {get_color("window-foreground")}; background: {get_color("window-background")};' +
'position: absolute; display: none; left: 0; top: 0; padding: 0.5ex; border: solid 2px; z-index: 3000',
id='reference-mode-overlay'
),
),
) )
handlers = { handlers = {
'ready': self.on_iframe_ready, 'ready': self.on_iframe_ready,
@ -216,6 +222,7 @@ class View:
'selectionchange': self.on_selection_change, 'selectionchange': self.on_selection_change,
'handle_shortcut': self.on_handle_shortcut, 'handle_shortcut': self.on_handle_shortcut,
'handle_keypress': self.on_handle_keypress, 'handle_keypress': self.on_handle_keypress,
'reference_item_changed': self.on_reference_item_changed,
} }
entry_point = None if runtime.is_standalone_viewer else 'read_book.iframe' entry_point = None if runtime.is_standalone_viewer else 'read_book.iframe'
if runtime.is_standalone_viewer: if runtime.is_standalone_viewer:
@ -236,6 +243,10 @@ class View:
def iframe(self): def iframe(self):
return self.iframe_wrapper.iframe return self.iframe_wrapper.iframe
@property
def reference_mode_overlay(self):
return document.getElementById('reference-mode-overlay')
def on_lookup_word(self, data): def on_lookup_word(self, data):
if runtime.is_standalone_viewer: if runtime.is_standalone_viewer:
ui_operations.selection_changed(data.word) ui_operations.selection_changed(data.word)
@ -366,6 +377,8 @@ class View:
self.bump_font_size({'increase': False}) self.bump_font_size({'increase': False})
elif data.name is 'toggle_full_screen': elif data.name is 'toggle_full_screen':
ui_operations.toggle_full_screen() ui_operations.toggle_full_screen()
elif data.name is 'toggle_reference_mode':
self.toggle_reference_mode()
elif data.name is 'reload_book': elif data.name is 'reload_book':
ui_operations.reload_book() ui_operations.reload_book()
elif data.name is 'search_for_selection': elif data.name is 'search_for_selection':
@ -456,6 +469,7 @@ class View:
self.overlay.hide() self.overlay.hide()
self.search_overlay.hide() self.search_overlay.hide()
self.content_popup_overlay.hide() self.content_popup_overlay.hide()
self.reference_mode_overlay.style.display = 'none'
self.focus_iframe() self.focus_iframe()
def focus_iframe(self): def focus_iframe(self):
@ -932,7 +946,7 @@ class View:
self.iframe_wrapper.send_unencrypted_message('display', self.iframe_wrapper.send_unencrypted_message('display',
resource_data=resource_data, book=self.book, name=self.currently_showing.name, resource_data=resource_data, book=self.book, name=self.currently_showing.name,
initial_position=self.currently_showing.initial_position, initial_position=self.currently_showing.initial_position,
settings=self.currently_showing.settings, settings=self.currently_showing.settings, reference_mode_enabled=self.reference_mode_enabled,
is_titlepage=self.currently_showing.name is self.book.manifest.title_page_name, is_titlepage=self.currently_showing.name is self.book.manifest.title_page_name,
) )
@ -941,6 +955,7 @@ class View:
self.hide_loading() self.hide_loading()
self.set_progress_frac(data.progress_frac, data.file_progress_frac) self.set_progress_frac(data.progress_frac, data.file_progress_frac)
self.update_header_footer() self.update_header_footer()
self.on_reference_item_changed()
window.scrollTo(0, 0) # ensure window is at 0 on mobile where the navbar causes issues window.scrollTo(0, 0) # ensure window is at 0 on mobile where the navbar causes issues
if self.book_load_started: if self.book_load_started:
self.book_load_started = False self.book_load_started = False
@ -958,3 +973,17 @@ class View:
def update_color_scheme(self): def update_color_scheme(self):
cs = self.get_color_scheme(True) cs = self.get_color_scheme(True)
self.iframe_wrapper.send_message('change_color_scheme', color_scheme=cs) self.iframe_wrapper.send_message('change_color_scheme', color_scheme=cs)
def toggle_reference_mode(self):
self.reference_mode_enabled = not self.reference_mode_enabled
self.iframe_wrapper.send_message('set_reference_mode', enabled=self.reference_mode_enabled)
def on_reference_item_changed(self, data):
data = data or {'refnum': None, 'index': None}
refnum, index = data.refnum, data.index
div = self.reference_mode_overlay
if refnum is None:
div.style.display = 'none'
else:
div.style.display = 'block'
div.textContent = f'{index}.{refnum}'