Skip to content

Commit

Permalink
More work on profiles
Browse files Browse the repository at this point in the history
  • Loading branch information
kovidgoyal committed Feb 21, 2024
1 parent 592dad1 commit 43338d6
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 47 deletions.
9 changes: 7 additions & 2 deletions src/calibre/gui2/viewer/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,18 @@ 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())
if isinstance(profile, dict):
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
if isinstance(profile, dict):
raw.setdefault(name, {})[profile_name] = profile
else:
if name in raw:
raw[name].pop(profile_name, None)
with open(os.path.join(viewer_config_dir, 'profiles.json'), 'wb') as f:
f.write(json.dumps(raw, indent=2, sort_keys=True).encode())
17 changes: 10 additions & 7 deletions src/calibre/gui2/viewer/web_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,6 @@ def requestStarted(self, rq):
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:
Expand Down Expand Up @@ -287,7 +284,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)
profile_op = from_js(object, object, object)

create_view = to_js()
start_book_load = to_js()
Expand All @@ -307,6 +304,7 @@ class ViewerBridge(Bridge):
repair_after_fullscreen_switch = to_js()
viewer_font_size_changed = to_js()
tts_event = to_js()
profile_response = to_js()


def apply_font_settings(page_or_view):
Expand Down Expand Up @@ -552,7 +550,7 @@ def __init__(self, parent=None):
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.profile_op.connect(self.profile_op)
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)
Expand All @@ -572,8 +570,13 @@ def __init__(self, parent=None):
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 profile_op(self, which, profile_name, settings):
if which == 'all-profiles':
vp = load_viewer_profiles('viewer:')
self.execute_when_ready('profile_response', 'all-profiles', vp)
elif which == 'save-profile':
save_viewer_profile(profile_name, settings, 'viewer:')
self.execute_when_ready('profile_response', 'save-profile', profile_name)

def link_hovered(self, url):
if url == 'javascript:void(0)':
Expand Down
76 changes: 59 additions & 17 deletions src/pyj/read_book/profiles.pyj
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ from __python__ import bound_methods, hash_literals
from elementmaker import E

from book_list.globals import get_session_data
from book_list.item_list import create_item, create_item_list, create_side_action
from dom import clear, unique_id
from gettext import gettext as _
from modals import question_dialog
from read_book.globals import ui_operations
from session import settings_for_reader_profile
from widgets import create_button
Expand All @@ -19,29 +21,72 @@ def save_profile(container_id, hide_panel):
name = container.querySelector('[name=profile_name]').value
sd = get_session_data()
settings = settings_for_reader_profile(sd)
ui_operations.save_profile(name, settings, def(err_msg):
if err_msg:
ui_operations.show_error(_('Unhandled error'), _('Could not save profile with error: ') + err_msg)
else:
container = document.getElementById(container_id)
if container:
r = container.querySelector('.saved_msg')
if r:
clear(r)
r.appendChild(E.div(E.i(_('Saved: ') + name), style='margin-top: 1rem; margin-bottom: 1rem'))
ui_operations.save_profile(name, settings, def():
container = document.getElementById(container_id)
if container:
r = container.querySelector('.saved_msg')
if r:
clear(r)
r.appendChild(E.div(E.i(_('Saved: ') + name), style='margin-top: 1rem; margin-bottom: 1rem'))
load_profiles(container_id)
)


def use_profile(container_id, profile_name, profile_data):
container = document.getElementById(container_id)
if not container:
return
container.dispatchEvent(new Event('close_panel'))


def delete_profile(container_id, profile_name):
question_dialog(_('Are you sure?'), _('Are you sure you want to delete the saved profile named: {}?').format(profile_name),
def (ok):
if ok:
ui_operations.save_profile(profile_name, None, def():
load_profiles(container_id)
)
)


def got_all_profiles(container_id, all_profiles):
container = document.getElementById(container_id)
if not container:
return
all_profiles['__default__'] = {}
names = list_wrap(Object.keys(all_profiles))
names.pysort(def(x): return '' if x is '__default__' else x.toLowerCase();)
pl = container.querySelector('.profiles_list_container')
clear(pl)
pl.appendChild(E.div(
_('Load settings from one of the previously saved profiles below…')
))
pl.appendChild(E.div())
items = []
for name in names:
display_name = name
if name is '__default__':
display_name = _('Restore settings to default values')
side_actions = []
else:
side_actions = [create_side_action('trash', delete_profile.bind(None, container_id, name), _('Delete this profile'))]
items.push(create_item(display_name, action=use_profile.bind(None, container_id, name, all_profiles[name]), side_actions=side_actions))
create_item_list(pl.lastChild, items)


def got_all_profiles(hide_panel, container_id, all_profiles):
def load_profiles(container_id):
container = document.getElementById(container_id)
if not container:
return
print(all_profiles)
pl = container.querySelector('.profiles_list_container')
clear(pl)
pl.appendChild(E.div(_('Loading saved profiles, please wait…'), style='padding-bottom: 1rem'))
ui_operations.get_all_profiles(got_all_profiles.bind(None, container_id))


def create_profiles_panel(hide_panel, book, container, onclick):
c = E.div(style='margin: 1rem', id=unique_id('placeholder-prefs'))
c.addEventListener('close_panel', def(): hide_panel();, False)
container_id = c.id
a = E.div(
style='display:flex',
Expand All @@ -61,8 +106,5 @@ def create_profiles_panel(hide_panel, book, container, onclick):
c.appendChild(a)
c.appendChild(E.div(class_='saved_msg'))
c.appendChild(E.hr())
c.appendChild(E.div(
style='padding-bottom: 1rem', class_='loading_msg',
_('Loading saved profiles, please wait…')
))
ui_operations.get_all_profiles(got_all_profiles.bind(None, hide_panel, container.id)
c.appendChild(E.div(class_='profiles_list_container'))
load_profiles(container_id)
38 changes: 17 additions & 21 deletions src/pyj/viewer-main.pyj
Original file line number Diff line number Diff line change
Expand Up @@ -72,28 +72,26 @@ 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 = JSON.parse(xhr.responseText)
else:
show_error(_('Failed to load profiles'), _(
'Could not load viewer profiles: unknown response type: {}').format(xhr.responseType))
return
profiles_callbacks = {'all': None, 'saved': None}

proceed(result)
@from_python
def profile_response(which, x):
if which is 'all-profiles':
profiles_callbacks.all(x)
profiles_callbacks.all = None
elif which is 'save-profile':
profiles_callbacks.saved()
profiles_callbacks.saved = None


def get_all_profiles(proceed):
xhr = ajax('all-profiles', profiles_recevied.bind(None, proceed), ok_code=0)
xhr.responseType = 'text'
xhr.send()
profiles_callbacks.all = proceed
to_python.profile_op('all-profiles', '', None)


def save_profile(name, settings, proceed):
profiles_callbacks.saved = proceed
to_python.profile_op('save-profile', name, settings)


def get_mathjax_files(proceed):
Expand Down Expand Up @@ -351,9 +349,7 @@ if window is window.top:
if TRANSLATIONS_DATA:
install(TRANSLATIONS_DATA)
ui_operations.get_all_profiles = get_all_profiles
ui_operations.save_profile = def(name, settings, proceed):
to_python.save_profile(name, settings)
proceed()
ui_operations.save_profile = save_profile
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
Expand Down

0 comments on commit 43338d6

Please sign in to comment.