From a37805bdc967d5cee64c7061af3d5a93576f4a88 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 13 Sep 2019 13:21:15 +0530 Subject: [PATCH] Add some UI to edit the book details CSS --- src/calibre/gui2/book_details.py | 12 +- src/calibre/gui2/preferences/look_feel.py | 16 +++ src/calibre/gui2/preferences/look_feel.ui | 140 ++++++++++++---------- src/calibre/utils/resources.py | 27 ++++- 4 files changed, 121 insertions(+), 74 deletions(-) diff --git a/src/calibre/gui2/book_details.py b/src/calibre/gui2/book_details.py index d0ee90d6b1..bf029f767e 100644 --- a/src/calibre/gui2/book_details.py +++ b/src/calibre/gui2/book_details.py @@ -36,7 +36,6 @@ from calibre.utils.serialize import json_loads from polyglot.binary import from_hex_bytes from polyglot.builtins import unicode_type -_css = None InternetSearch = namedtuple('InternetSearch', 'author where') @@ -53,12 +52,13 @@ def set_html(mi, html, text_browser): text_browser.setHtml(html) -def css(): - global _css - if _css is None: +def css(reset=False): + if reset: + del css.ans + if not hasattr(css, 'ans'): val = P('templates/book_details.css', data=True).decode('utf-8') - _css = re.sub(unicode_type(r'/\*.*?\*/'), '', val, flags=re.DOTALL) - return _css + css.ans = re.sub(unicode_type(r'/\*.*?\*/'), '', val, flags=re.DOTALL) + return css.ans def copy_all(text_browser): diff --git a/src/calibre/gui2/preferences/look_feel.py b/src/calibre/gui2/preferences/look_feel.py index 2b33989b67..b523ce842b 100644 --- a/src/calibre/gui2/preferences/look_feel.py +++ b/src/calibre/gui2/preferences/look_feel.py @@ -37,6 +37,7 @@ from calibre.gui2.preferences.coloring import EditRules from calibre.gui2.library.alternate_views import auto_height, CM_TO_INCH from calibre.gui2.widgets2 import Dialog from calibre.gui2.actions.show_quickview import get_quickview_action_plugin +from calibre.utils.resources import set_data from polyglot.builtins import iteritems, unicode_type, map @@ -571,6 +572,11 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.opt_cover_grid_disk_cache_size.setMaximum(self.gui.grid_view.thumbnail_cache.min_disk_cache * 100) self.opt_cover_grid_width.valueChanged.connect(self.update_aspect_ratio) self.opt_cover_grid_height.valueChanged.connect(self.update_aspect_ratio) + self.opt_book_details_css.textChanged.connect(self.changed_signal) + from calibre.gui2.tweak_book.editor.text import get_highlighter, get_theme + self.css_highlighter = get_highlighter('css')() + self.css_highlighter.apply_theme(get_theme(None)) + self.css_highlighter.set_document(self.opt_book_details_css.document()) def choose_icon_theme(self): from calibre.gui2.icon_theme import ChooseTheme @@ -643,6 +649,9 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.set_cg_color(gprefs['cover_grid_color']) self.set_cg_texture(gprefs['cover_grid_texture']) self.update_aspect_ratio() + self.opt_book_details_css.blockSignals(True) + self.opt_book_details_css.setPlainText(P('templates/book_details.css', data=True).decode('utf-8')) + self.opt_book_details_css.blockSignals(False) def open_cg_cache(self): open_local_file(self.gui.grid_view.thumbnail_cache.location) @@ -691,6 +700,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.changed_signal.emit() self.set_cg_color(gprefs.defaults['cover_grid_color']) self.set_cg_texture(gprefs.defaults['cover_grid_texture']) + self.opt_book_details_css.setPlainText(P('templates/book_details.css', allow_user_override=False, data=True).decode('utf-8')) def change_cover_grid_color(self): col = QColorDialog.getColor(self.cg_bg_widget.bcol, @@ -763,6 +773,12 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.commit_icon_theme() rr = True gprefs['default_author_link'] = self.default_author_link.value + bcss = self.opt_book_details_css.toPlainText().encode('utf-8') + defcss = P('templates/book_details.css', data=True, allow_user_override=False) + if defcss == bcss: + bcss = None + set_data('templates/book_details.css', bcss) + return rr def refresh_gui(self, gui): diff --git a/src/calibre/gui2/preferences/look_feel.ui b/src/calibre/gui2/preferences/look_feel.ui index f309dba7a2..e205f0575a 100644 --- a/src/calibre/gui2/preferences/look_feel.ui +++ b/src/calibre/gui2/preferences/look_feel.ui @@ -6,7 +6,7 @@ 0 0 - 843 + 839 580 @@ -727,57 +727,6 @@ A value of zero means calculate automatically. &Book details - - - - Select displayed metadata - - - - - - Move up - - - - :/images/arrow-up.png:/images/arrow-up.png - - - - - - - Move down - - - - :/images/arrow-down.png:/images/arrow-down.png - - - - - - - true - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - @@ -822,13 +771,6 @@ A value of zero means calculate automatically. - - - - Create rules to convert &identifiers into links - - - @@ -839,14 +781,84 @@ A value of zero means calculate automatically. - - + + - Note that <b>comments</b> will always be displayed at the end, regardless of the position you assign here. + Create rules to convert &identifiers into links - - true + + + + + + Text styling + + + + + + + + + + + Select displayed metadata + + + + + + Move down + + + + :/images/arrow-down.png:/images/arrow-down.png + + + + + + + Move up + + + + :/images/arrow-up.png:/images/arrow-up.png + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + true + + + + + + + Note that <b>comments</b> will always be displayed at the end, regardless of the position you assign here. + + + true + + + + diff --git a/src/calibre/utils/resources.py b/src/calibre/utils/resources.py index 0a952ad81b..f63b884fc3 100644 --- a/src/calibre/utils/resources.py +++ b/src/calibre/utils/resources.py @@ -13,6 +13,9 @@ from calibre import config_dir from polyglot.builtins import builtins +user_dir = os.path.join(config_dir, 'resources') + + class PathResolver(object): def __init__(self): @@ -39,11 +42,10 @@ class PathResolver(object): self.default_path = dev_path self.using_develop_from = True - user_path = os.path.join(config_dir, 'resources') self.user_path = None - if suitable(user_path): - self.locations.insert(0, user_path) - self.user_path = user_path + if suitable(user_dir): + self.locations.insert(0, user_dir) + self.user_path = user_dir def __call__(self, path, allow_user_override=True): path = path.replace(os.sep, '/') @@ -65,6 +67,19 @@ class PathResolver(object): return ans + def set_data(self, path, data=None): + self.cache.pop((path, True), None) + fpath = os.path.join(user_dir, *path.split('/')) + if data is None: + if os.path.exists(fpath): + os.remove(fpath) + else: + base = os.path.dirname(fpath) + if not os.path.exists(base): + os.makedirs(base) + with open(fpath, 'wb') as f: + f.write(data) + _resolver = PathResolver() @@ -83,5 +98,9 @@ def get_image_path(path, data=False, allow_user_override=True): return get_path('images/'+path, data=data, allow_user_override=allow_user_override) +def set_data(path, data=None): + return _resolver.set_data(path, data) + + builtins.__dict__['P'] = get_path builtins.__dict__['I'] = get_image_path