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