mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Implement reloading of book
This commit is contained in:
parent
b2be6727f6
commit
377b90ea0d
@ -122,7 +122,7 @@ def save_metadata(metadata, f):
|
||||
f.seek(0), f.truncate(), f.write(as_bytes(json.dumps(metadata, indent=2)))
|
||||
|
||||
|
||||
def prepare_book(path, convert_func=do_convert, max_age=30 * DAY):
|
||||
def prepare_book(path, convert_func=do_convert, max_age=30 * DAY, force=False):
|
||||
st = os.stat(path)
|
||||
key = book_hash(path, st.st_size, st.st_mtime)
|
||||
finished_path = safe_makedirs(os.path.join(book_cache_dir(), 'f'))
|
||||
@ -135,11 +135,15 @@ def prepare_book(path, convert_func=do_convert, max_age=30 * DAY):
|
||||
metadata = {'entries': {}, 'last_clear_at': 0}
|
||||
entries = metadata['entries']
|
||||
instances = entries.setdefault(key, [])
|
||||
for instance in instances:
|
||||
for instance in tuple(instances):
|
||||
if instance['status'] == 'finished':
|
||||
instance['atime'] = time.time()
|
||||
save_metadata(metadata, f)
|
||||
return os.path.join(finished_path, instance['path'])
|
||||
if force:
|
||||
robust_rmtree(os.path.join(finished_path, instance['path']))
|
||||
instances.remove(instance)
|
||||
else:
|
||||
instance['atime'] = time.time()
|
||||
save_metadata(metadata, f)
|
||||
return os.path.join(finished_path, instance['path'])
|
||||
instance = prepare_convert(temp_path, key, st)
|
||||
instances.append(instance)
|
||||
save_metadata(metadata, f)
|
||||
@ -234,6 +238,12 @@ def find_tests():
|
||||
third_path = prepare_book(book_src, convert_func=convert_mock)
|
||||
self.assertNotEqual(path, third_path)
|
||||
|
||||
# Test force reload
|
||||
fourth_path = prepare_book(book_src, convert_func=convert_mock)
|
||||
self.ae(third_path, fourth_path)
|
||||
fourth_path = prepare_book(book_src, convert_func=convert_mock, force=True)
|
||||
self.assertNotEqual(third_path, fourth_path)
|
||||
|
||||
# Test cache expiry
|
||||
open(book_src, 'wb').write(b'bcd')
|
||||
prepare_book(book_src, convert_func=convert_mock, max_age=-1000)
|
||||
|
@ -59,6 +59,7 @@ class EbookViewer(MainWindow):
|
||||
self.inspector_dock = create_dock(_('Inspector'), 'inspector', Qt.RightDockWidgetArea)
|
||||
self.web_view = WebView(self)
|
||||
self.web_view.cfi_changed.connect(self.cfi_changed)
|
||||
self.web_view.reload_book.connect(self.reload_book)
|
||||
self.setCentralWidget(self.web_view)
|
||||
|
||||
def handle_commandline_arg(self, arg):
|
||||
@ -76,18 +77,22 @@ class EbookViewer(MainWindow):
|
||||
self.load_ebook(path, open_at=open_at)
|
||||
self.raise_()
|
||||
|
||||
def load_ebook(self, pathtoebook, open_at=None):
|
||||
def load_ebook(self, pathtoebook, open_at=None, reload_book=False):
|
||||
# TODO: Implement open_at
|
||||
self.web_view.show_preparing_message()
|
||||
self.save_annotations()
|
||||
self.current_book_data = {}
|
||||
t = Thread(name='LoadBook', target=self._load_ebook_worker, args=(pathtoebook, open_at))
|
||||
t = Thread(name='LoadBook', target=self._load_ebook_worker, args=(pathtoebook, open_at, reload_book))
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
def _load_ebook_worker(self, pathtoebook, open_at):
|
||||
def reload_book(self):
|
||||
if self.current_book_data:
|
||||
self.load_ebook(self.current_book_data['pathtoebook'], reload_book=True)
|
||||
|
||||
def _load_ebook_worker(self, pathtoebook, open_at, reload_book):
|
||||
try:
|
||||
ans = prepare_book(pathtoebook)
|
||||
ans = prepare_book(pathtoebook, force=reload_book)
|
||||
except WorkerError as e:
|
||||
self.book_prepared.emit(False, {'exception': e, 'tb': e.orig_tb, 'pathtoebook': pathtoebook})
|
||||
except Exception as e:
|
||||
|
@ -167,6 +167,7 @@ def create_profile():
|
||||
class ViewerBridge(Bridge):
|
||||
|
||||
set_session_data = from_js(object, object)
|
||||
reload_book = from_js()
|
||||
|
||||
create_view = to_js()
|
||||
show_preparing_message = to_js()
|
||||
@ -244,6 +245,7 @@ class Inspector(QWidget):
|
||||
class WebView(RestartingWebEngineView):
|
||||
|
||||
cfi_changed = pyqtSignal(object)
|
||||
reload_book = pyqtSignal()
|
||||
|
||||
def __init__(self, parent=None):
|
||||
self._host_widget = None
|
||||
@ -256,6 +258,7 @@ class WebView(RestartingWebEngineView):
|
||||
self._page = WebPage(self)
|
||||
self.bridge.bridge_ready.connect(self.on_bridge_ready)
|
||||
self.bridge.set_session_data.connect(self.set_session_data)
|
||||
self.bridge.reload_book.connect(self.reload_book)
|
||||
self.pending_bridge_ready_actions = {}
|
||||
self.setPage(self._page)
|
||||
self.setAcceptDrops(False)
|
||||
|
@ -72,4 +72,6 @@ ui_operations = {
|
||||
'update_url_state': None,
|
||||
'update_last_read_time': None,
|
||||
'show_error': None,
|
||||
'redisplay_book': None,
|
||||
'reload_book': None,
|
||||
}
|
||||
|
@ -5,19 +5,21 @@ from __python__ import bound_methods, hash_literals
|
||||
from elementmaker import E
|
||||
from gettext import gettext as _
|
||||
|
||||
from book_list.globals import get_read_ui
|
||||
from book_list.library_data import sync_library_books
|
||||
from book_list.router import home
|
||||
from book_list.theme import get_color
|
||||
from dom import add_extra_css, build_rule, clear, set_css, svgicon, unique_id
|
||||
from modals import error_dialog
|
||||
from utils import full_screen_element, request_full_screen, safe_set_inner_html, is_ios
|
||||
from read_book.globals import ui_operations, runtime
|
||||
from read_book.goto import create_goto_panel
|
||||
from read_book.prefs.font_size import create_font_size_panel
|
||||
from read_book.prefs.main import create_prefs_panel
|
||||
from read_book.toc import create_toc_panel
|
||||
from read_book.word_actions import create_word_actions_panel
|
||||
from session import get_device_uuid
|
||||
from utils import (
|
||||
full_screen_element, is_ios, request_full_screen, safe_set_inner_html
|
||||
)
|
||||
from widgets import create_button, create_spinner
|
||||
|
||||
|
||||
@ -86,6 +88,10 @@ class DeleteBook: # {{{
|
||||
pass # Dont allow panel to be closed by a click
|
||||
|
||||
def delete_book(self):
|
||||
if runtime.is_standalone_viewer:
|
||||
if self.reload_book:
|
||||
ui_operations.reload_book()
|
||||
return
|
||||
self.show_working()
|
||||
view = self.overlay.view
|
||||
view.ui.db.delete_book(view.book, def(book, errmsg):
|
||||
@ -94,7 +100,7 @@ class DeleteBook: # {{{
|
||||
view.ui.show_error(_('Failed to delete book'), _('Failed to delete book from local storage, click "Show details" for more information.'), errmsg)
|
||||
else:
|
||||
if self.reload_book:
|
||||
get_read_ui().reload_book()
|
||||
ui_operations.reload_book()
|
||||
else:
|
||||
home()
|
||||
)
|
||||
@ -207,6 +213,14 @@ class MainOverlay:
|
||||
|
||||
return E.li(icon, '\xa0', text, onclick=action, title=tooltip)
|
||||
|
||||
sync_action = ac(_('Sync'), _('Get last read position and annotations from the server'), self.overlay.sync_book, 'cloud-download')
|
||||
delete_action = ac(_('Delete'), _('Delete this book from the device'), self.overlay.delete_book, 'trash')
|
||||
reload_action = ac(_('Reload'), _('Reload this book from the {}').format( _('computer') if runtime.is_standalone_viewer else _('server')), self.overlay.reload_book, 'refresh')
|
||||
if runtime.is_standalone_viewer:
|
||||
reload_actions = E.ul(reload_action)
|
||||
else:
|
||||
reload_actions = E.ul(sync_action, delete_action, reload_action)
|
||||
|
||||
actions_div = E.div( # actions
|
||||
E.ul(
|
||||
ac(_('Home'), _('Return to list of books'), def(): home();, 'home'),
|
||||
@ -219,11 +233,7 @@ class MainOverlay:
|
||||
ac(_('Go to'), _('Go to a specific location in the book'), self.overlay.show_goto, 'chevron-right'),
|
||||
),
|
||||
|
||||
E.ul(
|
||||
ac(_('Sync'), _('Get last read position and annotations from the server'), self.overlay.sync_book, 'cloud-download'),
|
||||
ac(_('Delete'), _('Delete this book from the device'), self.overlay.delete_book, 'trash'),
|
||||
ac(_('Reload'), _('Reload this book from the server'), self.overlay.reload_book, 'refresh')
|
||||
),
|
||||
reload_actions,
|
||||
|
||||
E.ul(
|
||||
ac(_('Table of Contents'), None, self.overlay.show_toc, 'TC', True),
|
||||
@ -350,7 +360,7 @@ class PrefsOverlay: # {{{
|
||||
def on_hide(self):
|
||||
if self.changes_occurred:
|
||||
self.changes_occurred = False
|
||||
get_read_ui().redisplay_book()
|
||||
ui_operations.redisplay_book()
|
||||
|
||||
# }}}
|
||||
|
||||
|
@ -60,6 +60,8 @@ class ReadUI:
|
||||
ui_operations.update_url_state = self.update_url_state.bind(self)
|
||||
ui_operations.update_last_read_time = self.db.update_last_read_time
|
||||
ui_operations.show_error = self.show_error.bind(self)
|
||||
ui_operations.redisplay_book = self.redisplay_book.bind(self)
|
||||
ui_operations.reload_book = self.reload_book.bind(self)
|
||||
|
||||
def on_resize(self):
|
||||
self.view.on_resize()
|
||||
|
@ -206,12 +206,22 @@ def onerror(msg, script_url, line_number, column_number, error_object):
|
||||
return True
|
||||
|
||||
|
||||
def redisplay_book():
|
||||
view.redisplay_book()
|
||||
|
||||
|
||||
def reload_book():
|
||||
to_python.reload_book()
|
||||
|
||||
|
||||
if window is window.top:
|
||||
# main
|
||||
ui_operations.get_file = get_file
|
||||
ui_operations.get_mathjax_files = get_mathjax_files
|
||||
ui_operations.update_url_state = update_url_state
|
||||
ui_operations.show_error = show_error
|
||||
ui_operations.redisplay_book = redisplay_book
|
||||
ui_operations.reload_book = reload_book
|
||||
document.body.appendChild(E.div(id='view'))
|
||||
window.onerror = onerror
|
||||
create_modal_container()
|
||||
|
Loading…
x
Reference in New Issue
Block a user