diff --git a/src/calibre/gui2/tweak_book/__init__.py b/src/calibre/gui2/tweak_book/__init__.py index 65c7a6901c..67b5b5a7d1 100644 --- a/src/calibre/gui2/tweak_book/__init__.py +++ b/src/calibre/gui2/tweak_book/__init__.py @@ -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'} diff --git a/src/calibre/gui2/tweak_book/boss.py b/src/calibre/gui2/tweak_book/boss.py index 0b6807460e..6d26417bbe 100644 --- a/src/calibre/gui2/tweak_book/boss.py +++ b/src/calibre/gui2/tweak_book/boss.py @@ -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) diff --git a/src/calibre/gui2/tweak_book/preferences.py b/src/calibre/gui2/tweak_book/preferences.py index 79af4714f8..a9bb6f5be7 100644 --- a/src/calibre/gui2/tweak_book/preferences.py +++ b/src/calibre/gui2/tweak_book/preferences.py @@ -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 {{{ diff --git a/src/calibre/gui2/tweak_book/preview.py b/src/calibre/gui2/tweak_book/preview.py index bd11f5f625..37aac8e50f 100644 --- a/src/calibre/gui2/tweak_book/preview.py +++ b/src/calibre/gui2/tweak_book/preview.py @@ -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(_( '''