Skip to content

Commit 1fa9258

Browse files
committed
Annotations browser: include custom highlight styles in Restrict to dropdown
The 'Restrict to' dropdown in the Annotations browser only listed built-in highlight presets (Yellow, Green, Blue, Red, Purple, Wavy, Strikeout). Custom highlight presets created by the user were not shown. Two changes: 1. backend.py all_annotation_styles(): scan the database for annotations whose style has type='custom' and merge those style definitions into the returned dictionary alongside the built-in styles. 2. annotations.py Restrictions.re_initialize(): use friendly_name from the style dict as the display label for custom styles, instead of passing the style name through annotation_title() which is designed for annotation types, not style names.
1 parent 56ef1fc commit 1fa9258

2 files changed

Lines changed: 31 additions & 5 deletions

File tree

src/calibre/db/backend.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2638,10 +2638,30 @@ def all_annotation_types(self):
26382638
def all_annotation_styles(self):
26392639
all_styles = [{'kind': 'color', 'which': style} for style in builtin_colors_light.keys()] + \
26402640
[{'kind': 'decoration', 'which': style} for style in builtin_decorations.keys()]
2641-
# In the future, we could merge in custom styles from the DB.
2642-
# Under the current schema, this would require scanning all annotations,
2643-
# so it's excluded for performance at this time.
2644-
return {style['which']: style for style in all_styles}
2641+
ans = {style['which']: style for style in all_styles}
2642+
# Merge in custom highlight styles found in the database. Custom
2643+
# styles are stored as JSON inside the annot_data column with
2644+
# 'type': 'custom' and a 'friendly_name' key. We scan the DB to
2645+
# discover them, since they are not part of the built-in set.
2646+
try:
2647+
for (raw_annot_data,) in self.execute(
2648+
"SELECT annot_data FROM annotations"
2649+
" WHERE json_extract(annot_data, '$.style.type') = 'custom'"
2650+
" AND json_extract(annot_data, '$.removed') IS NULL"
2651+
):
2652+
try:
2653+
style = json.loads(raw_annot_data).get('style')
2654+
except Exception:
2655+
continue
2656+
if style is not None and isinstance(style, dict):
2657+
name = style.get('friendly_name') or style.get('which')
2658+
if name and name not in ans:
2659+
ans[name] = style
2660+
except Exception:
2661+
# Best-effort: if the query fails (e.g. schema mismatch) just
2662+
# return the built-in styles.
2663+
pass
2664+
return ans
26452665

26462666
def set_annotations_for_book(self, book_id, fmt, annots_list, user_type='local', user='viewer'):
26472667
try:

src/calibre/gui2/library/annotations.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -870,7 +870,13 @@ def re_initialize(self, db, restrict_to_book_ids=None):
870870
all_styles = db.all_annotation_styles()
871871
translate = _
872872
for style_name, style in all_styles.items():
873-
item = QStandardItem(translate(annotation_title(style_name)))
873+
# Custom styles store their display name in friendly_name;
874+
# built-in styles use annotation_title on the style name.
875+
if style.get('type') == 'custom':
876+
label = style.get('friendly_name', style_name)
877+
else:
878+
label = annotation_title(style_name)
879+
item = QStandardItem(translate(label))
874880
item.setData({'type': 'highlight', 'style': style}, Qt.ItemDataRole.UserRole)
875881
dec = decoration_for_style(self.palette(), style, self.icon_size, dpr, is_dark)
876882
if dec:

0 commit comments

Comments
 (0)