mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Change how background image works in preparation for profiles
Allow multiple background images and allow settings from browser and desktop readers to work with each other
This commit is contained in:
parent
558992008a
commit
3cbcd0acc9
@ -77,18 +77,26 @@ def get_data(name):
|
||||
return None, None
|
||||
|
||||
|
||||
def background_image():
|
||||
ans = getattr(background_image, 'ans', None)
|
||||
if ans is None:
|
||||
@lru_cache(maxsize=4)
|
||||
def background_image(encoded_fname=''):
|
||||
if not encoded_fname:
|
||||
img_path = os.path.join(viewer_config_dir, 'bg-image.data')
|
||||
if os.path.exists(img_path):
|
||||
try:
|
||||
with open(img_path, 'rb') as f:
|
||||
data = f.read()
|
||||
mt, data = data.split(b'|', 1)
|
||||
else:
|
||||
ans = b'image/jpeg', b''
|
||||
ans = background_image.ans = mt.decode('utf-8'), data
|
||||
return ans
|
||||
mt = mt.decode()
|
||||
return mt, data
|
||||
except FileNotFoundError:
|
||||
return 'image/jpeg', b''
|
||||
fname = bytes.fromhex(encoded_fname).decode()
|
||||
img_path = os.path.join(viewer_config_dir, 'background-images', fname)
|
||||
mt = guess_type(fname)[0] or 'image/jpeg'
|
||||
try:
|
||||
with open(img_path, 'rb') as f:
|
||||
return mt, f.read()
|
||||
except FileNotFoundError:
|
||||
return mt, b''
|
||||
|
||||
|
||||
@lru_cache(maxsize=2)
|
||||
@ -161,10 +169,11 @@ class UrlSchemeHandler(QWebEngineUrlSchemeHandler):
|
||||
send_reply(rq, set_book_path.manifest_mime, data)
|
||||
elif name == 'reader-background':
|
||||
mt, data = background_image()
|
||||
if data:
|
||||
send_reply(rq, mt, data)
|
||||
else:
|
||||
rq.fail(QWebEngineUrlRequestJob.Error.UrlNotFound)
|
||||
send_reply(rq, mt, data) if data else rq.fail(QWebEngineUrlRequestJob.Error.UrlNotFound)
|
||||
elif name.startswith('reader-background-'):
|
||||
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.startswith('mathjax/'):
|
||||
handle_mathjax_request(rq, name)
|
||||
elif not name:
|
||||
@ -693,14 +702,16 @@ class WebView(RestartingWebEngineView):
|
||||
self.execute_when_ready('show_home_page')
|
||||
|
||||
def change_background_image(self, img_id):
|
||||
files = choose_images(self, 'viewer-background-image', _('Choose background image'), formats=['png', 'gif', 'jpg', 'jpeg'])
|
||||
files = choose_images(self, 'viewer-background-image', _('Choose background image'), formats=['png', 'gif', 'jpg', 'jpeg', 'webp'])
|
||||
if files:
|
||||
img = files[0]
|
||||
with open(img, 'rb') as src, open(os.path.join(viewer_config_dir, 'bg-image.data'), 'wb') as dest:
|
||||
dest.write(as_bytes(guess_type(img)[0] or 'image/jpeg') + b'|')
|
||||
shutil.copyfileobj(src, dest)
|
||||
d = os.path.join(viewer_config_dir, 'background-images')
|
||||
os.makedirs(d, exist_ok=True)
|
||||
fname = os.path.basename(img)
|
||||
shutil.copyfile(img, os.path.join(d, fname))
|
||||
background_image.ans = None
|
||||
self.execute_when_ready('background_image_changed', img_id)
|
||||
encoded = fname.encode().hex()
|
||||
self.execute_when_ready('background_image_changed', img_id, f'{FAKE_PROTOCOL}://{FAKE_HOST}/reader-background-{encoded}')
|
||||
|
||||
def goto_frac(self, frac):
|
||||
self.execute_when_ready('goto_frac', frac)
|
||||
|
@ -30,7 +30,9 @@ from calibre.srv.routes import endpoint, json
|
||||
from calibre.srv.utils import get_db, get_use_roman, http_date
|
||||
from calibre.utils.config_base import tweaks
|
||||
from calibre.utils.date import timestampfromdt
|
||||
from calibre.utils.filenames import ascii_filename, atomic_rename
|
||||
from calibre.utils.filenames import (
|
||||
ascii_filename, atomic_rename, make_long_path_useable,
|
||||
)
|
||||
from calibre.utils.img import image_from_data, scale_image
|
||||
from calibre.utils.localization import _
|
||||
from calibre.utils.resources import get_image_path as I, get_path as P
|
||||
@ -303,6 +305,19 @@ def icon(ctx, rd, which):
|
||||
return ans
|
||||
|
||||
|
||||
@endpoint('/reader-background/{encoded_fname}', android_workaround=True)
|
||||
def reader_background(ctx, rd, encoded_fname):
|
||||
base = os.path.abspath(os.path.normapth(os.path.join(config_dir, 'viewer', 'background-images')))
|
||||
fname = bytes.fromhex(encoded_fname)
|
||||
q = os.path.abspath(os.path.normpath(os.path.join(base, fname)))
|
||||
if not q.startswith(base):
|
||||
raise HTTPNotFound(f'Reader background {encoded_fname} not found')
|
||||
try:
|
||||
return share_open(make_long_path_useable(q), 'rb')
|
||||
except FileNotFoundError:
|
||||
raise HTTPNotFound(f'Reader background {encoded_fname} not found')
|
||||
|
||||
|
||||
@endpoint('/get/{what}/{book_id}/{library_id=None}', android_workaround=True)
|
||||
def get(ctx, rd, what, book_id, library_id):
|
||||
book_id, rest = book_id.partition('_')[::2]
|
||||
|
@ -3,14 +3,16 @@
|
||||
from __python__ import bound_methods, hash_literals
|
||||
|
||||
from elementmaker import E
|
||||
from gettext import gettext as _
|
||||
|
||||
from ajax import absolute_path
|
||||
from book_list.globals import get_session_data
|
||||
from dom import ensure_id, unique_id
|
||||
from encodings import hexlify
|
||||
from gettext import gettext as _
|
||||
from read_book.globals import runtime, ui_operations
|
||||
from read_book.prefs.utils import create_button_box
|
||||
from session import session_defaults
|
||||
from viewer.constants import READER_BACKGROUND_URL
|
||||
from viewer.constants import FAKE_HOST, FAKE_PROTOCOL
|
||||
from widgets import create_button
|
||||
|
||||
BLANK = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
|
||||
@ -21,19 +23,33 @@ def change_background_image(img_id):
|
||||
|
||||
|
||||
def clear_image(img_id):
|
||||
document.getElementById(img_id).src = BLANK
|
||||
i = document.getElementById(img_id)
|
||||
i.src = BLANK
|
||||
i.dataset.url = ''
|
||||
|
||||
|
||||
def modify_background_image_url_for_fetch(url):
|
||||
if not url:
|
||||
return BLANK
|
||||
if runtime.is_standalone_viewer:
|
||||
if url.startswith(f'{FAKE_PROTOCOL}:'):
|
||||
return url
|
||||
encoded = hexlify(url)
|
||||
return f'{FAKE_PROTOCOL}://{FAKE_HOST}/reader-background-{encoded}'
|
||||
if url.startswith(f'{FAKE_PROTOCOL}:'):
|
||||
x = str.split(url, '/')[-1].partition('?')[0].partition('-')[2]
|
||||
return absolute_path(f'reader-background/{x}')
|
||||
return url
|
||||
|
||||
|
||||
def standalone_background_widget(sd):
|
||||
if sd.get('background_image'):
|
||||
src = READER_BACKGROUND_URL
|
||||
else:
|
||||
src = BLANK
|
||||
url = sd.get('background_image')
|
||||
src = modify_background_image_url_for_fetch(url)
|
||||
img_id = unique_id('bg-image')
|
||||
|
||||
return E.div(
|
||||
style='display: flex; align-items: center',
|
||||
E.div(E.img(src=src, id=img_id, class_='bg-image-preview', style='width: 75px; height: 75px; border: solid 1px')),
|
||||
E.div(E.img(src=src, data_url=url, id=img_id, class_='bg-image-preview', style='width: 75px; height: 75px; border: solid 1px')),
|
||||
E.div('\xa0', style='margin: 0.5rem'),
|
||||
create_button(_('Change image'), action=change_background_image.bind(None, img_id)),
|
||||
E.div('\xa0', style='margin: 0.5rem'),
|
||||
@ -77,7 +93,8 @@ def restore_defaults():
|
||||
container = document.getElementById(create_user_stylesheet_panel.container_id)
|
||||
container.querySelector('[name=user-stylesheet]').value = ''
|
||||
if runtime.is_standalone_viewer:
|
||||
clear_image(container.querySelector('img').id)
|
||||
i = container.querySelector('img')
|
||||
clear_image(i.id)
|
||||
else:
|
||||
container.querySelector('[name=background_image]').value = ''
|
||||
container.querySelector('select[name=background_image_style]').value = session_defaults().background_image_style
|
||||
@ -132,8 +149,8 @@ def commit_user_stylesheet(onchange, container):
|
||||
sd.set('user_stylesheet', val)
|
||||
changed = True
|
||||
if runtime.is_standalone_viewer:
|
||||
bg_image = container.querySelector('img.bg-image-preview').src
|
||||
if bg_image is BLANK:
|
||||
bg_image = container.querySelector('img.bg-image-preview').dataset.url
|
||||
if bg_image is BLANK or not bg_image:
|
||||
bg_image = None
|
||||
else:
|
||||
bg_image = container.querySelector('input[name=background_image]').value
|
||||
|
@ -33,6 +33,7 @@ from read_book.prefs.head_foot import render_head_foot
|
||||
from read_book.prefs.scrolling import (
|
||||
MIN_SCROLL_SPEED_AUTO as SCROLL_SPEED_STEP, change_scroll_speed
|
||||
)
|
||||
from read_book.prefs.user_stylesheet import modify_background_image_url_for_fetch
|
||||
from read_book.read_aloud import ReadAloud
|
||||
from read_book.read_audio_ebook import ReadAudioEbook
|
||||
from read_book.resources import load_resources
|
||||
@ -49,7 +50,6 @@ from utils import (
|
||||
default_context_menu_should_be_allowed, html_escape, is_ios, parse_url_params,
|
||||
safe_set_inner_html, username_key
|
||||
)
|
||||
from viewer.constants import READER_BACKGROUND_URL
|
||||
|
||||
add_extra_css(def():
|
||||
sel = '.book-side-margin'
|
||||
@ -851,7 +851,7 @@ class View:
|
||||
iframe.style.backgroundColor = ans.background or 'white'
|
||||
bg_image = sd.get('background_image')
|
||||
if bg_image:
|
||||
iframe.style.backgroundImage = f'url({READER_BACKGROUND_URL}?{Date().getTime()})' if runtime.is_standalone_viewer else f'url({bg_image})'
|
||||
iframe.style.backgroundImage = f'url({modify_background_image_url_for_fetch(bg_image)})'
|
||||
else:
|
||||
iframe.style.backgroundImage = 'none'
|
||||
if sd.get('background_image_style') is 'scaled':
|
||||
|
@ -26,7 +26,7 @@ from read_book.prefs.head_foot import set_time_formatter
|
||||
from read_book.view import View
|
||||
from session import local_storage, session_defaults, default_interface_data
|
||||
from utils import debounce, encode_query_with_path, parse_url_params
|
||||
from viewer.constants import FAKE_HOST, FAKE_PROTOCOL, READER_BACKGROUND_URL
|
||||
from viewer.constants import FAKE_HOST, FAKE_PROTOCOL
|
||||
|
||||
runtime.is_standalone_viewer = True
|
||||
runtime.FAKE_HOST = FAKE_HOST
|
||||
@ -267,10 +267,11 @@ def goto_frac(frac):
|
||||
|
||||
|
||||
@from_python
|
||||
def background_image_changed(img_id):
|
||||
def background_image_changed(img_id, url):
|
||||
img = document.getElementById(img_id)
|
||||
if img:
|
||||
img.src = READER_BACKGROUND_URL + '?' + Date().getTime()
|
||||
img.src = f'{url}?{Date().getTime()}'
|
||||
img.dataset.url = url
|
||||
|
||||
|
||||
@from_python
|
||||
|
@ -5,4 +5,3 @@ from __python__ import bound_methods, hash_literals
|
||||
|
||||
FAKE_PROTOCOL = '__FAKE_PROTOCOL__'
|
||||
FAKE_HOST = '__FAKE_HOST__'
|
||||
READER_BACKGROUND_URL = f'{FAKE_PROTOCOL}://{FAKE_HOST}/reader-background'
|
||||
|
Loading…
x
Reference in New Issue
Block a user