mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
More work on reader profiles
This commit is contained in:
parent
32a4423efb
commit
6be3293166
@ -7,6 +7,7 @@ import tempfile
|
||||
|
||||
from calibre.constants import cache_dir, config_dir
|
||||
from calibre.utils.config import JSONConfig
|
||||
from calibre.utils.date import isoformat, utcnow
|
||||
from calibre.utils.filenames import atomic_rename
|
||||
|
||||
vprefs = JSONConfig('viewer-webengine')
|
||||
@ -73,3 +74,52 @@ def save_reading_rates(key, rates):
|
||||
def load_reading_rates(key):
|
||||
existing = get_existing_reading_rates()
|
||||
return existing.get(key)
|
||||
|
||||
|
||||
def expand_profile_user_names(user_names):
|
||||
user_names = set(user_names)
|
||||
sau = get_session_pref('sync_annots_user', default='')
|
||||
if sau:
|
||||
if sau == '*':
|
||||
sau = 'user:'
|
||||
if 'viewer:' in user_names:
|
||||
user_names.add(sau)
|
||||
elif sau in user_names:
|
||||
user_names.add('viewer:')
|
||||
return user_names
|
||||
|
||||
|
||||
def load_viewer_profiles(*user_names: str, as_json_string=False):
|
||||
user_names = expand_profile_user_names(user_names)
|
||||
ans = {}
|
||||
try:
|
||||
with open(os.path.join(viewer_config_dir, 'profiles.json'), 'rb') as f:
|
||||
raw = json.loads(f.read())
|
||||
except FileNotFoundError:
|
||||
if as_json_string:
|
||||
return '{}'
|
||||
return ans
|
||||
for uname, profiles in raw.items():
|
||||
if uname in user_names:
|
||||
for profile_name, profile in profiles.items():
|
||||
if profile_name not in ans or ans[profile_name]['__timestamp__'] <= profile['__timestamp__']:
|
||||
ans[profile_name] = profile
|
||||
if as_json_string:
|
||||
return json.dumps(ans)
|
||||
return ans
|
||||
|
||||
|
||||
def save_viewer_profile(profile_name, profile, *user_names: str):
|
||||
user_names = expand_profile_user_names(user_names)
|
||||
if isinstance(profile, (str, bytes)):
|
||||
profile = json.loads(profile)
|
||||
profile['__timestamp__'] = isoformat(utcnow())
|
||||
try:
|
||||
with open(os.path.join(viewer_config_dir, 'profiles.json'), 'rb') as f:
|
||||
raw = json.loads(f.read())
|
||||
except FileNotFoundError:
|
||||
raw = {}
|
||||
for name in user_names:
|
||||
raw.setdefault(name, {})[profile_name] = profile
|
||||
with open(os.path.join(viewer_config_dir, 'profiles.json'), 'wb') as f:
|
||||
f.write(json.dumps(raw, indent=2, sort_keys=True).encode())
|
||||
|
@ -25,7 +25,9 @@ from calibre.gui2 import choose_images, config, error_dialog, safe_open_url
|
||||
from calibre.gui2.viewer import (
|
||||
link_prefix_for_location_links, performance_monitor, url_for_book_in_library,
|
||||
)
|
||||
from calibre.gui2.viewer.config import viewer_config_dir, vprefs
|
||||
from calibre.gui2.viewer.config import (
|
||||
load_viewer_profiles, save_viewer_profile, viewer_config_dir, vprefs,
|
||||
)
|
||||
from calibre.gui2.viewer.tts import TTS
|
||||
from calibre.gui2.webengine import RestartingWebEngineView
|
||||
from calibre.srv.code import get_translations_data
|
||||
@ -188,6 +190,9 @@ class UrlSchemeHandler(QWebEngineUrlSchemeHandler):
|
||||
encoded_fname = name[len('reader-background-'):]
|
||||
mt, data = background_image(encoded_fname)
|
||||
send_reply(rq, mt, data) if data else rq.fail(QWebEngineUrlRequestJob.Error.UrlNotFound)
|
||||
elif name == 'all-profiles':
|
||||
vp = load_viewer_profiles('viewer:', as_json_string=True)
|
||||
send_reply(rq, 'application/json', vp.encode())
|
||||
elif name.startswith('mathjax/'):
|
||||
handle_mathjax_request(rq, name)
|
||||
elif not name:
|
||||
@ -282,6 +287,7 @@ class ViewerBridge(Bridge):
|
||||
show_book_folder = from_js()
|
||||
show_help = from_js(object)
|
||||
update_reading_rates = from_js(object)
|
||||
save_profile = from_js(object, object)
|
||||
|
||||
create_view = to_js()
|
||||
start_book_load = to_js()
|
||||
@ -546,6 +552,7 @@ class WebView(RestartingWebEngineView):
|
||||
self.bridge.close_prep_finished.connect(self.close_prep_finished)
|
||||
self.bridge.highlights_changed.connect(self.highlights_changed)
|
||||
self.bridge.update_reading_rates.connect(self.update_reading_rates)
|
||||
self.bridge.save_profile.connect(self.save_profile)
|
||||
self.bridge.edit_book.connect(self.edit_book)
|
||||
self.bridge.show_book_folder.connect(self.show_book_folder)
|
||||
self.bridge.show_help.connect(self.show_help)
|
||||
@ -565,6 +572,9 @@ class WebView(RestartingWebEngineView):
|
||||
self.inspector = Inspector(parent.inspector_dock.toggleViewAction(), self)
|
||||
parent.inspector_dock.setWidget(self.inspector)
|
||||
|
||||
def save_profile(self, name, settings):
|
||||
save_viewer_profile(name, settings, 'viewer:')
|
||||
|
||||
def link_hovered(self, url):
|
||||
if url == 'javascript:void(0)':
|
||||
url = ''
|
||||
|
@ -29,8 +29,8 @@ all_settings = {
|
||||
'base_font_size': {'default': 16, 'category': 'read_book', 'is_local': True},
|
||||
'book_scrollbar': {'default': False, 'category': 'read_book'},
|
||||
'columns_per_screen': {'default': {'portrait':0, 'landscape':0}, 'category': 'read_book', 'is_local': True},
|
||||
'controls_help_shown_count': {'default': 0, 'category': 'read_book', 'is_local': True},
|
||||
'controls_help_shown_count_rtl_page_progression': {'default': 0, 'category': 'read_book', 'is_local': True},
|
||||
'controls_help_shown_count': {'default': 0, 'category': 'read_book', 'is_local': True, 'disallowed_in_profile': True},
|
||||
'controls_help_shown_count_rtl_page_progression': {'default': 0, 'category': 'read_book', 'is_local': True, 'disallowed_in_profile': True},
|
||||
'cover_preserve_aspect_ratio': {'default': True, 'category': 'read_book'},
|
||||
'current_color_scheme': {'default': 'system', 'category': 'read_book'},
|
||||
'footer': {'default': {'right': 'progress'}, 'category': 'read_book'},
|
||||
@ -58,7 +58,7 @@ all_settings = {
|
||||
'scroll_stop_boundaries': {'default': False, 'category': 'read_book', 'is_local': True},
|
||||
'standalone_font_settings': {'default': {}, 'category': 'read_book', 'is_local': True},
|
||||
'standalone_misc_settings': {'default': {}, 'category': 'read_book', 'is_local': True},
|
||||
'standalone_recently_opened': {'default': v'[]', 'category': 'read_book', 'is_local': True},
|
||||
'standalone_recently_opened': {'default': v'[]', 'category': 'read_book', 'is_local': True, 'disallowed_in_profile': True},
|
||||
'user_color_schemes': {'default': {}, 'category': 'read_book'},
|
||||
'user_stylesheet': {'default': '', 'category': 'read_book', 'is_local': True},
|
||||
'word_actions': {'default': v'[]', 'category': 'read_book'},
|
||||
@ -69,14 +69,15 @@ all_settings = {
|
||||
'net_search_url': {'default': 'https://google.com/search?q={q}', 'category': 'read_book'},
|
||||
'selection_bar_actions': {'default': v"['copy', 'lookup', 'highlight', 'remove_highlight', 'search_net', 'clear']", 'category': 'read_book'},
|
||||
'selection_bar_quick_highlights': {'default': v"[]", 'category': 'read_book'},
|
||||
'skipped_dialogs': {'default': v'{}', 'category': 'read_book', 'is_local': True},
|
||||
'tts': {'default': v'{}', 'category': 'read_book', 'is_local': True},
|
||||
'tts_backend': {'default': v'{}', 'category': 'read_book', 'is_local': True},
|
||||
'skipped_dialogs': {'default': v'{}', 'category': 'read_book', 'is_local': True, 'disallowed_in_profile': True},
|
||||
'tts': {'default': v'{}', 'category': 'read_book', 'is_local': True, 'disallowed_in_profile': True},
|
||||
'tts_backend': {'default': v'{}', 'category': 'read_book', 'is_local': True, 'disallowed_in_profile': True},
|
||||
'fullscreen_when_opening': {'default': 'auto', 'category': 'read_book', 'is_local': True},
|
||||
'book_search_mode': {'default': 'contains', 'category': 'read_book', 'is_local': True},
|
||||
'book_search_case_sensitive': {'default': False, 'category': 'read_book', 'is_local': True},
|
||||
'reverse_page_turn_zones': {'default': False, 'category': 'read_book', 'is_local': True},
|
||||
'gesture_overrides': {'default': {}, 'category': 'read_book'},
|
||||
'current_profile': {'default': None, 'category': 'read_book', 'is_local': True, 'disallowed_in_profile': True},
|
||||
}
|
||||
|
||||
defaults = {}
|
||||
@ -230,10 +231,20 @@ def get_subset_of_settings(sd, filter_func):
|
||||
metadata = all_settings[setting_name]
|
||||
is_set = curval is not ans
|
||||
if filter_func(setting_name, metadata, is_set):
|
||||
ans[setting_name] = curval if is_set else metadata.default
|
||||
ans[setting_name] = window.structuredClone(curval if is_set else metadata.default)
|
||||
return ans
|
||||
|
||||
|
||||
def settings_for_reader_profile(sd):
|
||||
|
||||
def filter_func(setting_name, metadata, is_set):
|
||||
if not is_set or metadata.category is not 'read_book' or metadata.disallowed_in_profile:
|
||||
return False
|
||||
return True
|
||||
|
||||
return get_subset_of_settings(sd, filter_func)
|
||||
|
||||
|
||||
default_interface_data = {
|
||||
'username': None,
|
||||
'output_format': 'EPUB',
|
||||
|
@ -72,6 +72,32 @@ def get_file(book, name, proceed):
|
||||
xhr.send()
|
||||
|
||||
|
||||
def profiles_recevied(proceed, end_type, xhr, ev):
|
||||
end_type = workaround_qt_bug(xhr, end_type)
|
||||
if end_type is 'abort':
|
||||
return
|
||||
if end_type is not 'load':
|
||||
show_error(_('Failed to load profiles'), _(
|
||||
'Could not load viewer profiles with error: {}').format(xhr.error_html))
|
||||
return
|
||||
if not xhr.responseType or xhr.responseType is 'text':
|
||||
result = xhr.responseText
|
||||
else if xhr.responseType is 'blob':
|
||||
result = xhr.response
|
||||
else:
|
||||
show_error(_('Failed to load profiles'), _(
|
||||
'Could not load viewer profiles: unknown response type: {}').format(xhr.responseType))
|
||||
return
|
||||
|
||||
proceed(result)
|
||||
|
||||
|
||||
def get_all_profiles(proceed):
|
||||
xhr = ajax('all-profiles/', profiles_recevied.bind(None, proceed), ok_code=0)
|
||||
xhr.responseType = 'text'
|
||||
xhr.send()
|
||||
|
||||
|
||||
def get_mathjax_files(proceed):
|
||||
proceed({})
|
||||
|
||||
@ -326,6 +352,9 @@ if window is window.top:
|
||||
TRANSLATIONS_DATA = v'__TRANSLATIONS_DATA__'
|
||||
if TRANSLATIONS_DATA:
|
||||
install(TRANSLATIONS_DATA)
|
||||
ui_operations.get_all_profiles = get_all_profiles
|
||||
ui_operations.save_profile = def(name, settings):
|
||||
to_python.save_profile(name, settings)
|
||||
ui_operations.get_file = get_file
|
||||
ui_operations.get_url_for_book_file_name = get_url_for_book_file_name
|
||||
ui_operations.get_mathjax_files = get_mathjax_files
|
||||
|
Loading…
x
Reference in New Issue
Block a user