UI for viewer font settings

This commit is contained in:
Kovid Goyal 2019-08-12 20:27:33 +05:30
parent 6100a4eeee
commit 7914ad4244
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
5 changed files with 179 additions and 14 deletions

View File

@ -9,8 +9,8 @@ import sys
from itertools import count
from PyQt5.Qt import (
QApplication, QBuffer, QByteArray, QHBoxLayout, QSize, Qt, QTimer, QUrl, QWidget,
pyqtSignal
QApplication, QBuffer, QByteArray, QFontDatabase, QHBoxLayout, QSize, Qt, QTimer,
QUrl, QWidget, pyqtSignal
)
from PyQt5.QtWebEngineCore import QWebEngineUrlSchemeHandler
from PyQt5.QtWebEngineWidgets import (
@ -188,6 +188,35 @@ class ViewerBridge(Bridge):
get_current_cfi = to_js()
def apply_font_settings(page_or_view):
s = page_or_view.settings()
sd = vprefs['session_data']
fs = sd.get('standalone_font_settings', {})
if fs.get('serif_family'):
s.setFontFamily(s.SerifFont, fs.get('serif_family'))
else:
s.resetFontFamily(s.SerifFont)
if fs.get('sans_family'):
s.setFontFamily(s.SansSerifFont, fs.get('sans_family'))
else:
s.resetFontFamily(s.SansSerifFont)
if fs.get('mono_family'):
s.setFontFamily(s.FixedFont, fs.get('mono_family'))
else:
s.resetFontFamily(s.SansSerifFont)
sf = fs.get('standard_font') or 'serif'
sf = getattr(s, {'serif': 'SerifFont', 'sans': 'SansSerifFont', 'mono': 'FixedFont'}[sf])
s.setFontFamily(s.StandardFont, s.fontFamily(sf))
mfs = fs.get('minimum_font_size')
if mfs is None:
s.resetFontSize(s.MinimumFontSize)
else:
s.setFontSize(s.MinimumFontSize, mfs)
s.setFontSize(s.DefaultFontSize, sd.get('base_font_size'))
return s
class WebPage(QWebEnginePage):
def __init__(self, parent):
@ -195,6 +224,7 @@ class WebPage(QWebEnginePage):
QWebEnginePage.__init__(self, profile, parent)
profile.setParent(self)
secure_webengine(self, for_viewer=True)
apply_font_settings(self)
self.bridge = ViewerBridge(self)
def javaScriptConsoleMessage(self, level, msg, linenumber, source_id):
@ -309,6 +339,11 @@ class WebView(RestartingWebEngineView):
if ans is not None and not sip.isdeleted(ans):
return ans
def change_zoom_by(self, steps=1):
ss = vprefs['session_data'].get('zoom_step_size') or 20
amt = (ss / 100) * steps
self._page.setZoomFactor(self._page.zoomFactor() + amt)
def render_process_died(self):
if self.dead_renderer_error_shown:
return
@ -339,7 +374,7 @@ class WebView(RestartingWebEngineView):
return self._page.bridge
def on_bridge_ready(self):
self.bridge.create_view(vprefs['session_data'])
self.bridge.create_view(vprefs['session_data'], QFontDatabase().families())
for func, args in iteritems(self.pending_bridge_ready_actions):
getattr(self.bridge, func)(*args)
@ -369,9 +404,12 @@ class WebView(RestartingWebEngineView):
def set_session_data(self, key, val):
if key == '*' and val is None:
vprefs['session_data'] = {}
else:
apply_font_settings(self._page)
elif key != '*':
sd = vprefs['session_data']
sd[key] = val
if key == 'standalone_font_settings':
apply_font_settings(self._page)
vprefs['session_data'] = sd
def do_callback(self, func_name, callback):

View File

@ -0,0 +1,108 @@
# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
from __python__ import hash_literals, bound_methods
from gettext import gettext as _
from dom import unique_id
from elementmaker import E
from book_list.globals import get_session_data
from read_book.globals import runtime
CONTAINER = unique_id('standalone-font-settings')
DEFAULT_STANDARD_FONT = 'serif'
DEFAULT_MINIMUM_FONT_SIZE = 8
DEFAULT_ZOOM_STEP_SIZE = 20
def font_select(name, settings):
ans = E.select(name=name)
ans.appendChild(E.option(_('— Choose a font —'), value=''))
current_val = settings[name]
if not current_val:
ans.lastChild.setAttribute('selected', 'selected')
for family in runtime.all_font_families:
if family:
ans.appendChild(E.option(family))
if family is current_val:
ans.lastChild.setAttribute('selected', 'selected')
return ans
def standard_font(settings):
ans = E.select(name='standard_font')
ans.appendChild(E.option(_('Serif'), value='serif'))
ans.appendChild(E.option(_('Sans-serif'), value='sans'))
ans.appendChild(E.option(_('Monospace'), value='mono'))
sf = settings.standard_font or DEFAULT_STANDARD_FONT
ans.querySelector(f'[value={sf}]').setAttribute('selected', 'selected')
return ans
def minimum_font_size(settings):
ans = E.input(max='100', min='0', step='1', type='number', name='minimum_font_size')
if jstype(settings.minimum_font_size) is 'number':
ans.value = settings.minimum_font_size + ''
else:
ans.value = '' + DEFAULT_MINIMUM_FONT_SIZE
return ans
def zoom_step_size(settings):
ans = E.input(max='100', min='1', step='1', type='number', name='zoom_step_size')
if jstype(settings.zoom_step_size) is 'number':
ans.value = settings.zoom_step_size + ''
else:
ans.value = '' + DEFAULT_ZOOM_STEP_SIZE
return ans
def get_container():
return document.getElementById(CONTAINER)
def create_fonts_panel(container):
container.appendChild(E.div(id=CONTAINER, style='margin: 1rem'))
container = container.lastChild
container.append(E.div(_('Choose fonts to use for un-styled text:'), style='margin-top: 1rem'))
sd = get_session_data()
settings = sd.get('standalone_font_settings')
def row(label, widget):
return E.tr(E.td(label + ':\xa0', style='padding-top: 1ex'), E.td(widget, style='padding-top: 1ex'))
container.append(E.table(style='margin-top: 1rem',
row(_('Serif family'), font_select('serif_family', settings)),
row(_('Sans-serif family'), font_select('sans_family', settings)),
row(_('Monospace family'), font_select('mono_family', settings)),
row(_('Standard font'), standard_font(settings)),
))
container.append(E.div(_('Zoom related settings'), style='margin-top: 1rem'))
container.append(E.table(style='margin-top: 1rem',
row(_('Zoom step size (%s)'), zoom_step_size(settings)),
row(_('Minimum font size (px)'), minimum_font_size(settings)),
))
develop = create_fonts_panel
def commit_fonts(onchange):
sd = get_session_data()
container = get_container()
vals = {}
zss = parseInt(container.querySelector('[name=zoom_step_size]').value)
if zss is not DEFAULT_ZOOM_STEP_SIZE:
vals.zoom_step_size = zss
mfs = parseInt(container.querySelector('[name=minimum_font_size]').value)
if mfs is not DEFAULT_MINIMUM_FONT_SIZE:
vals.minimum_font_size = mfs
sf = container.querySelector('[name=standard_font]').value
if sf is not DEFAULT_STANDARD_FONT:
vals.standard_font = sf
for q in ('serif_family', 'sans_family', 'mono_family'):
val = container.querySelector(f'[name={q}]').value
if val:
vals[q] = val
sd.set('standalone_font_settings', vals)

View File

@ -1,15 +1,20 @@
# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
from __python__ import hash_literals, bound_methods
from __python__ import bound_methods, hash_literals
from gettext import gettext as _
from dom import svgicon, ensure_id, clear
from elementmaker import E
from gettext import gettext as _
from book_list.item_list import build_list, create_item
from read_book.prefs.colors import create_colors_panel, commit_colors
from read_book.prefs.layout import create_layout_panel, commit_layout
from read_book.prefs.user_stylesheet import create_user_stylesheet_panel, commit_user_stylesheet
from read_book.prefs.head_foot import create_head_foot_panel, commit_head_foot
from dom import clear, ensure_id, svgicon
from read_book.globals import runtime
from read_book.prefs.colors import commit_colors, create_colors_panel
from read_book.prefs.fonts import commit_fonts, create_fonts_panel
from read_book.prefs.head_foot import commit_head_foot, create_head_foot_panel
from read_book.prefs.layout import commit_layout, create_layout_panel
from read_book.prefs.user_stylesheet import (
commit_user_stylesheet, create_user_stylesheet_panel
)
class Prefs:
@ -59,12 +64,23 @@ class Prefs:
document.getElementById(self.title_id).textContent = _('Configure book reader')
c = E.div()
container.appendChild(c)
build_list(c, [
items = [
create_item(_('Colors'), def():self.show_panel('colors');, _('Colors of the page and text')),
create_item(_('Page layout'), def():self.show_panel('layout');, _('Page margins and number of pages per screen')),
create_item(_('User style sheet'), def():self.show_panel('user_stylesheet');, _('Style rules for text')),
create_item(_('Headers and footers'), def():self.show_panel('head_foot');, _('Customize the headers and footers')),
])
]
if runtime.is_standalone_viewer:
items.push(create_item(
_('Fonts'), def():self.show_panel('fonts');, _('Font choices')))
build_list(c, items)
def display_fonts(self, container):
document.getElementById(self.title_id).textContent = _('Fonts')
create_fonts_panel(container)
def close_fonts(self):
commit_fonts(self.onchange, self.container)
def display_colors(self, container):
document.getElementById(self.title_id).textContent = _('Colors')

View File

@ -40,6 +40,7 @@ defaults = {
'header': {},
'footer': {'right': 'progress'},
'word_actions': v'[]',
'standalone_font_settings': {},
}
is_local_setting = {
@ -55,6 +56,7 @@ is_local_setting = {
'current_color_scheme': True,
'base_font_size': True,
'controls_help_shown_count': True,
'standalone_font_settings': True,
}

View File

@ -175,8 +175,9 @@ def create_session_data(prefs):
@from_python
def create_view(prefs):
def create_view(prefs, all_font_families):
nonlocal view
runtime.all_font_families = all_font_families
if view is None:
create_session_data(prefs)
view = View(document.getElementById('view'))