Edit book: Allow customizing the base background/foreground and link colors for the preview window. Fixes #1889925 [[Enhancement] Editor Preview customise background colour](https://bugs.launchpad.net/calibre/+bug/1889925)

This commit is contained in:
Kovid Goyal 2020-08-01 12:20:52 +05:30
parent 95c4381900
commit 716db6162b
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 110 additions and 25 deletions

View File

@ -38,6 +38,9 @@ d['preview_standard_font_family'] = 'serif'
d['preview_base_font_size'] = 18
d['preview_mono_font_size'] = 14
d['preview_minimum_font_size'] = 8
d['preview_background'] = 'auto'
d['preview_foreground'] = 'auto'
d['preview_link_color'] = 'auto'
d['remove_existing_links_when_linking_sheets'] = True
d['charmap_favorites'] = list(map(ord, '\xa0\u2002\u2003\u2009\xad' '‘’“”‹›«»‚„' '—–§¶†‡©®™' '→⇒•·°±−×÷¼½½¾' '…µ¢£€¿¡¨´¸ˆ˜' 'ÀÁÂÃÄÅÆÇÈÉÊË' 'ÌÍÎÏÐÑÒÓÔÕÖØ' 'ŒŠÙÚÛÜÝŸÞßàá' 'âãäåæçèéêëìí' 'îïðñòóôõöøœš' 'ùúûüýÿþªºαΩ∞')) # noqa
d['folders_for_types'] = {'style':'styles', 'image':'images', 'font':'fonts', 'audio':'audio', 'video':'video'}

View File

@ -207,6 +207,7 @@ class Boss(QObject):
setup_css_parser_serialization()
self.gui.apply_settings()
self.refresh_file_list()
self.gui.preview.start_refresh_timer()
if ret == p.Accepted or p.dictionaries_changed:
for ed in itervalues(editors):
ed.apply_settings(dictionaries_changed=p.dictionaries_changed)

View File

@ -19,7 +19,7 @@ from PyQt5.Qt import (
QListWidgetItem, QIcon, QWidget, QSize, QFormLayout, Qt, QSpinBox,
QCheckBox, pyqtSignal, QDoubleSpinBox, QComboBox, QLabel, QFont, QApplication,
QFontComboBox, QPushButton, QSizePolicy, QHBoxLayout, QGroupBox,
QToolButton, QVBoxLayout, QSpacerItem, QTimer)
QToolButton, QVBoxLayout, QSpacerItem, QTimer, QRadioButton)
from calibre import prepare_string_for_xml
from calibre.utils.localization import get_lang
@ -30,6 +30,7 @@ from calibre.gui2.tweak_book.editor.themes import default_theme, all_theme_names
from calibre.gui2.tweak_book.spell import ManageDictionaries
from calibre.gui2.font_family_chooser import FontFamilyChooser
from calibre.gui2.tweak_book.widgets import Dialog
from calibre.gui2.widgets2 import ColorButton
class BasicSettings(QWidget): # {{{
@ -154,7 +155,7 @@ class BasicSettings(QWidget): # {{{
# }}}
class EditorSettings(BasicSettings):
class EditorSettings(BasicSettings): # {{{
def __init__(self, parent=None):
BasicSettings.__init__(self, parent)
@ -269,9 +270,10 @@ class EditorSettings(BasicSettings):
s.setter(s.widget, current_val)
if d.theme_name:
s.setter(s.widget, d.theme_name)
# }}}
class IntegrationSettings(BasicSettings):
class IntegrationSettings(BasicSettings): # {{{
def __init__(self, parent=None):
BasicSettings.__init__(self, parent)
@ -293,9 +295,10 @@ class IntegrationSettings(BasicSettings):
order.setToolTip(_('When auto-selecting the format to edit for a book with'
' multiple formats, this is the preference order.'))
l.addRow(_('Preferred format order (drag and drop to change)'), order)
# }}}
class MainWindowSettings(BasicSettings):
class MainWindowSettings(BasicSettings): # {{{
def __init__(self, parent=None):
BasicSettings.__init__(self, parent)
@ -334,9 +337,10 @@ class MainWindowSettings(BasicSettings):
' multiple files with the same file name.'
))
l.addRow(nd)
# }}}
class PreviewSettings(BasicSettings):
class PreviewSettings(BasicSettings): # {{{
def __init__(self, parent=None):
BasicSettings.__init__(self, parent)
@ -377,6 +381,51 @@ class PreviewSettings(BasicSettings):
w = self('preview_minimum_font_size')
w.setMinimum(4), w.setMaximum(100), w.setSuffix(' px')
l.addRow(_('Mi&nimum font size:'), w)
l.addRow(_('Background color:'), self.color_override('preview_background'))
l.addRow(_('Foreground color:'), self.color_override('preview_foreground'))
l.addRow(_('Link color:'), self.color_override('preview_link_color'))
def color_override(self, name):
w = QWidget(self)
l = QHBoxLayout(w)
def b(name, text, tt):
ans = QRadioButton(text, w)
l.addWidget(ans)
ans.setToolTip(tt)
setattr(w, name, ans)
ans.setObjectName(name)
return ans
b('unset', _('No change'), _('Use the colors from the book styles, defaulting to black-on-white'))
b('auto', _('Theme based'), _('When using a dark theme force dark colors, otherwise same as "No change"'))
b('manual', _('Custom'), _('Choose a custom color'))
c = w.color_button = ColorButton(parent=w)
l.addWidget(c)
connect_lambda(c.clicked, w, lambda w: w.manual.setChecked(True))
def getter(w):
if w.unset.isChecked():
return 'unset'
if w.auto.isChecked():
return 'auto'
return w.color_button.color or 'auto'
def setter(w, val):
val = val or 'auto'
if val == 'unset':
w.unset.setChecked(True)
elif val == 'auto':
w.auto.setChecked(True)
else:
w.manual.setChecked(True)
w.color_button.color = val
self(name, widget=w, getter=getter, setter=setter)
l.setContentsMargins(0, 0, 0, 0)
return w
# }}}
# ToolbarSettings {{{

View File

@ -26,7 +26,7 @@ from calibre.constants import (
from calibre.ebooks.oeb.base import OEB_DOCS, XHTML_MIME, serialize
from calibre.ebooks.oeb.polish.parsing import parse
from calibre.gui2 import NO_URL_FORMATTING, error_dialog, is_dark_theme, open_url
from calibre.gui2.palette import dark_color, dark_text_color
from calibre.gui2.palette import dark_color, dark_link_color, dark_text_color
from calibre.gui2.tweak_book import TOP, actions, current_container, editors, tprefs
from calibre.gui2.tweak_book.file_list import OpenWithHandler
from calibre.gui2.viewer.web_view import handle_mathjax_request, send_reply
@ -251,30 +251,35 @@ def create_profile():
create_script('csscolorparser.js', cparser),
create_script('editor.js', js),
create_script('dark-mode.js', '''
(function() {if (%s) {
var dark_bg = "%s", dark_fg = "%s", css = %s;
(function() {
var settings = JSON.parse(navigator.userAgent.split('|')[1]);
var dark_css = CSS;
function apply_body_colors(event) {
if (document.documentElement) {
if (settings.bg) document.documentElement.style.backgroundColor = settings.bg;
if (settings.fg) document.documentElement.style.color = settings.fg;
}
if (document.body) {
if (settings.bg) document.body.style.backgroundColor = settings.bg;
if (settings.fg) document.body.style.color = settings.fg;
}
}
function apply_css() {
var css = '';
if (settings.link) css += 'html > body :link, html > body :link * { color: ' + settings.link + ' !important; }';
if (settings.is_dark_theme) { css += dark_css; }
var style = document.createElement('style');
style.textContent = css;
document.documentElement.appendChild(style);
apply_body_colors();
}
function apply_dark_mode(event) {
if (document.documentElement) {
document.documentElement.style.backgroundColor = dark_bg;
document.documentElement.style.color = dark_fg;
}
if (document.body) {
document.body.style.backgroundColor = dark_bg;
document.body.style.color = dark_fg;
}
}
apply_dark_mode();
apply_body_colors();
document.addEventListener("DOMContentLoaded", apply_css);
document.addEventListener("DOMContentLoaded", apply_dark_mode);
} })();
''' % (
'true' if is_dark_theme() else 'false', dark_color.name(), dark_text_color.name(), json.dumps(dark_mode_css)),
})();
'''.replace('CSS', json.dumps(dark_mode_css), 1),
injection_point=QWebEngineScript.DocumentCreation)
)
url_handler = UrlSchemeHandler(ans)
@ -392,10 +397,37 @@ class WebView(RestartingWebEngineView, OpenWithHandler):
def sizeHint(self):
return self._size_hint
def update_settings(self):
dark = is_dark_theme()
def get_color(name, dark_val):
ans = tprefs[name]
if ans == 'auto' and dark:
ans = dark_val.name()
if ans in ('auto', 'unset'):
return None
return ans
settings = {
'is_dark_theme': dark,
'bg': get_color('preview_background', dark_color),
'fg': get_color('preview_foreground', dark_text_color),
'link': get_color('preview_link_color', dark_link_color),
}
p = self._page.profile()
ua = p.httpUserAgent().split('|')[0] + '|' + json.dumps(settings)
p.setHttpUserAgent(ua)
def refresh(self):
self.update_settings()
self.pageAction(QWebEnginePage.ReloadAndBypassCache).trigger()
def set_url(self, qurl):
self.update_settings()
RestartingWebEngineView.setUrl(self, qurl)
def clear(self):
self.update_settings()
self.setHtml(_(
'''
<h3>Live preview</h3>
@ -612,7 +644,7 @@ class Preview(QWidget):
self.current_name = name
self.report_worker_launch_error()
parse_worker.add_request(name)
self.view.setUrl(self.name_to_qurl())
self.view.set_url(self.name_to_qurl())
return True
def refresh(self):
@ -627,7 +659,7 @@ class Preview(QWidget):
self.refresh_starting.emit()
if current_url != self.view.url():
# The container was changed
self.view.setUrl(current_url)
self.view.set_url(current_url)
else:
self.view.refresh()
self.refreshed.emit()