From b9cb19580479598d9b7953f0c553743a83cd1997 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 26 Oct 2019 17:18:21 +0530 Subject: [PATCH] Viewer: Allow also using --open-at with book positions --- src/calibre/gui2/viewer/main.py | 6 +++--- src/calibre/gui2/viewer/ui.py | 15 +++++++++++++-- src/calibre/gui2/viewer/web_view.py | 4 ++-- src/pyj/read_book/goto.pyj | 3 +-- src/pyj/read_book/ui.pyj | 4 ++++ src/pyj/read_book/view.pyj | 9 ++++++++- src/pyj/viewer-main.pyj | 10 ++++++---- 7 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/calibre/gui2/viewer/main.py b/src/calibre/gui2/viewer/main.py index 88ea9b7f69..133e991829 100644 --- a/src/calibre/gui2/viewer/main.py +++ b/src/calibre/gui2/viewer/main.py @@ -14,7 +14,7 @@ from PyQt5.QtWebEngineCore import QWebEngineUrlScheme from calibre import as_unicode, prints from calibre.constants import FAKE_PROTOCOL, VIEWER_APP_UID, islinux from calibre.gui2 import Application, error_dialog, setup_gui_option_parser -from calibre.gui2.viewer.ui import EbookViewer +from calibre.gui2.viewer.ui import EbookViewer, is_float from calibre.ptempfile import reset_base_dir from calibre.utils.config import JSONConfig from calibre.utils.ipc import RC, viewer_socket_address @@ -163,7 +163,7 @@ View an e-book. help=_('Force reload of all opened books')) a('--open-at', default=None, help=_( 'The position at which to open the specified book. The position is ' - 'a location you can get by using the Goto action in the viewer controls. ' + 'a location or position you can get by using the Go to->Location action in the viewer controls. ' 'Alternately, you can use the form toc:something and it will open ' 'at the location of the first Table of Contents entry that contains ' 'the string "something".')) @@ -188,7 +188,7 @@ def main(args=sys.argv): parser = option_parser() opts, args = parser.parse_args(args) - if opts.open_at and not (opts.open_at.startswith('toc:') or opts.open_at.startswith('epubcfi(/')): + if opts.open_at and not (opts.open_at.startswith('toc:') or opts.open_at.startswith('epubcfi(/') or is_float(opts.open_at)): raise SystemExit('Not a valid --open-at value: {}'.format(opts.open_at)) listener = None diff --git a/src/calibre/gui2/viewer/ui.py b/src/calibre/gui2/viewer/ui.py index 3726c02da0..60bf4397a1 100644 --- a/src/calibre/gui2/viewer/ui.py +++ b/src/calibre/gui2/viewer/ui.py @@ -46,6 +46,15 @@ from polyglot.builtins import as_bytes, itervalues annotations_dir = os.path.join(viewer_config_dir, 'annots') +def is_float(x): + try: + float(x) + return True + except Exception: + pass + return False + + def dock_defs(): Dock = namedtuple('Dock', 'name title initial_area allowed_areas') ans = {} @@ -353,13 +362,15 @@ class EbookViewer(MainWindow): self.load_book_data() self.update_window_title() initial_cfi = self.initial_cfi_for_current_book() - initial_toc_node = None + initial_toc_node = initial_bookpos = None if open_at: if open_at.startswith('toc:'): initial_toc_node = self.toc_model.node_id_for_text(open_at[len('toc:'):]) elif open_at.startswith('epubcfi(/'): initial_cfi = open_at - self.web_view.start_book_load(initial_cfi=initial_cfi, initial_toc_node=initial_toc_node) + elif is_float(open_at): + initial_bookpos = float(open_at) + self.web_view.start_book_load(initial_cfi=initial_cfi, initial_toc_node=initial_toc_node, initial_bookpos=initial_bookpos) def load_book_data(self): self.load_book_annotations() diff --git a/src/calibre/gui2/viewer/web_view.py b/src/calibre/gui2/viewer/web_view.py index 5ba4840a37..092adda02c 100644 --- a/src/calibre/gui2/viewer/web_view.py +++ b/src/calibre/gui2/viewer/web_view.py @@ -502,9 +502,9 @@ class WebView(RestartingWebEngineView): for func, args in iteritems(self.pending_bridge_ready_actions): getattr(self.bridge, func)(*args) - def start_book_load(self, initial_cfi=None, initial_toc_node=None): + def start_book_load(self, initial_cfi=None, initial_toc_node=None, initial_bookpos=None): key = (set_book_path.path,) - self.execute_when_ready('start_book_load', key, initial_cfi, initial_toc_node, set_book_path.pathtoebook) + self.execute_when_ready('start_book_load', key, initial_cfi, initial_toc_node, initial_bookpos, set_book_path.pathtoebook) def execute_when_ready(self, action, *args): if self.bridge.ready: diff --git a/src/pyj/read_book/goto.pyj b/src/pyj/read_book/goto.pyj index c13b8029d4..4775687790 100644 --- a/src/pyj/read_book/goto.pyj +++ b/src/pyj/read_book/goto.pyj @@ -118,8 +118,7 @@ def create_location_overlay(current_position_data, overlay, container): def goto_pos(): src = document.querySelector(f'#{container_id} [name=newpos]') - val = max(0, min(1000 * float(src.value) / current_position_data.book_length, 1)) - ui_operations.goto_frac(val) + ui_operations.goto_book_position(float(src.value)) overlay.hide() container.lastChild.appendChild(E.div( diff --git a/src/pyj/read_book/ui.pyj b/src/pyj/read_book/ui.pyj index 181dd27157..4996096301 100644 --- a/src/pyj/read_book/ui.pyj +++ b/src/pyj/read_book/ui.pyj @@ -67,6 +67,7 @@ class ReadUI: ui_operations.update_font_size = self.update_font_size.bind(self) ui_operations.goto_cfi = self.goto_cfi.bind(self) ui_operations.goto_frac = self.goto_frac.bind(self) + ui_operations.goto_book_position = self.goto_book_position.bind(self) ui_operations.delete_book = self.delete_book.bind(self) ui_operations.focus_iframe = self.focus_iframe.bind(self) ui_operations.toggle_toc = self.toggle_toc.bind(self) @@ -166,6 +167,9 @@ class ReadUI: def goto_frac(self, frac): return self.view.goto_frac(frac) + def goto_book_position(self, bpos): + return self.view.goto_book_position(bpos) + def delete_book(self, book, proceed): self.db.delete_book(book, proceed) diff --git a/src/pyj/read_book/view.pyj b/src/pyj/read_book/view.pyj index 2022cb92c3..7bc0194a14 100644 --- a/src/pyj/read_book/view.pyj +++ b/src/pyj/read_book/view.pyj @@ -567,7 +567,7 @@ class View: cfi = '/' + rest return name, cfi - def display_book(self, book, initial_cfi, initial_toc_node): + def display_book(self, book, initial_cfi, initial_toc_node, initial_bookpos): self.hide_overlays() self.iframe.focus() is_current_book = self.book and self.book.key == book.key @@ -601,6 +601,9 @@ class View: navigated = False if jstype(initial_toc_node) is 'number': navigated = self.goto_toc_node(initial_toc_node) + if not navigated and jstype(initial_bookpos) is 'number': + navigated = True + self.goto_book_position(initial_bookpos) if not navigated: self.show_name(name, initial_position=pos) sd = get_session_data() @@ -694,6 +697,10 @@ class View: else: self.show_name(chapter_name, initial_position={'type':'frac', 'frac':chapter_frac, 'replace_history':True}) + def goto_book_position(self, bpos): + val = max(0, min(1000 * float(bpos) / self.current_position_data.book_length, 1)) + return self.goto_frac(val) + def on_scroll_to_anchor(self, data): self.show_name(data.name, initial_position={'type':'anchor', 'anchor':data.frag, 'replace_history':False}) diff --git a/src/pyj/viewer-main.pyj b/src/pyj/viewer-main.pyj index 16e920eded..159fd89e70 100644 --- a/src/pyj/viewer-main.pyj +++ b/src/pyj/viewer-main.pyj @@ -136,7 +136,7 @@ def show_error(title, msg, details): to_python.show_error(title, msg, details) -def manifest_received(key, initial_cfi, initial_toc_node, pathtoebook, end_type, xhr, ev): +def manifest_received(key, initial_cfi, initial_toc_node, initial_bookpos, pathtoebook, end_type, xhr, ev): nonlocal book if end_type is 'load': book = new_book(key, {}) @@ -148,7 +148,7 @@ def manifest_received(key, initial_cfi, initial_toc_node, pathtoebook, end_type, book.is_complete = True v'delete book.manifest["metadata"]' v'delete book.manifest["last_read_positions"]' - view.display_book(book, initial_cfi, initial_toc_node) + view.display_book(book, initial_cfi, initial_toc_node, initial_bookpos) else: show_error(_('Could not open book'), _( 'Failed to load book manifest, click "Show details" for more info'), @@ -230,8 +230,8 @@ def show_home_page(): @from_python -def start_book_load(key, initial_cfi, initial_toc_node, pathtoebook): - xhr = ajax('manifest', manifest_received.bind(None, key, initial_cfi, initial_toc_node, pathtoebook), ok_code=0) +def start_book_load(key, initial_cfi, initial_toc_node, initial_bookpos, pathtoebook): + xhr = ajax('manifest', manifest_received.bind(None, key, initial_cfi, initial_toc_node, initial_bookpos, pathtoebook), ok_code=0) xhr.responseType = 'json' xhr.send() @@ -308,6 +308,8 @@ if window is window.top: return view.goto_cfi(cfi) ui_operations.goto_frac = def(frac): return view.goto_frac(frac) + ui_operations.goto_book_position = def(bpos): + return view.goto_book_position(bpos) ui_operations.toggle_toc = def(): to_python.toggle_toc() ui_operations.toggle_bookmarks = def():