diff --git a/imgsrc/notes.svg b/imgsrc/notes.svg
new file mode 100644
index 0000000000..0f2c9b411d
--- /dev/null
+++ b/imgsrc/notes.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/resources/images/notes.png b/resources/images/notes.png
new file mode 100644
index 0000000000..3cb208d577
Binary files /dev/null and b/resources/images/notes.png differ
diff --git a/src/calibre/ebooks/metadata/book/render.py b/src/calibre/ebooks/metadata/book/render.py
index 7eaf109c28..b1b5e4833c 100644
--- a/src/calibre/ebooks/metadata/book/render.py
+++ b/src/calibre/ebooks/metadata/book/render.py
@@ -105,24 +105,33 @@ def mi_to_html(
mi,
field_list=None, default_author_link=None, use_roman_numbers=True,
rating_font='Liberation Serif', rtl=False, comments_heading_pos='hide',
- for_qt=False, vertical_fields=(), show_links=True,
+ for_qt=False, vertical_fields=(), show_links=True, all_notes=None
):
link_markup = '↗️'
if for_qt:
link_markup = '
'
+ note_markup = '
'
def get_link_map(column):
try:
return mi.link_maps[column]
except Exception:
return {}
- def add_other_link(field, field_value):
+ def add_other_links(field, field_value):
if show_links:
link = get_link_map(field).get(field_value)
if link:
link = prepare_string_for_xml(link, True)
- return ' {2}'.format(_('Click to open'), link, link_markup)
+ link = ' {2}'.format(_('Click to open'), link, link_markup)
+ else:
+ link = ''
+ if field_value in all_notes.get(field, set()):
+ note = ' {2}'.format(_('Click to open note'),
+ action('note', field=field, value=field_value), note_markup)
+ else:
+ note = ''
+ return link + note
return ''
if field_list is None:
@@ -294,7 +303,7 @@ def mi_to_html(
url=link, name=aut, title=lt), aut)
else:
val = aut
- val += add_other_link('authors', aut)
+ val += add_other_links('authors', aut)
authors.append(val)
ans.append((field, row % (name, value_list(' & ', authors))))
elif field == 'languages':
@@ -313,7 +322,7 @@ def mi_to_html(
search_action_with_data('publisher', mi.publisher, book_id),
_('Click to see books with {0}: {1}').format(metadata['name'], a(mi.publisher)),
p(mi.publisher))
- val += add_other_link('publisher', mi.publisher)
+ val += add_other_links('publisher', mi.publisher)
else:
val = p(mi.publisher)
ans.append((field, row % (name, val)))
@@ -345,7 +354,7 @@ def mi_to_html(
sidx=fmt_sidx(sidx, use_roman=use_roman_numbers), cls="series_name",
series=p(series), href=search_action_with_data(st, series, book_id, field),
tt=p(_('Click to see books in this series')))
- val += add_other_link(field, series)
+ val += add_other_links(field, series)
elif metadata['datatype'] == 'datetime':
aval = getattr(mi, field)
if is_date_undefined(aval):
@@ -374,7 +383,7 @@ def mi_to_html(
v = '{}'.format(
search_action_with_data(st, x, book_id, field), _('Click to see books with {0}: {1}').format(
metadata['name'] or field, a(x)), p(x))
- v += add_other_link(field, x)
+ v += add_other_links(field, x)
links.append(v)
val = value_list(metadata['is_multiple']['list_to_ui'], links)
elif metadata['datatype'] == 'text' or metadata['datatype'] == 'enumeration':
@@ -386,7 +395,7 @@ def mi_to_html(
v = '{}'.format(
search_action_with_data(st, unescaped_val, book_id, field), a(
_('Click to see books with {0}: {1}').format(metadata['name'] or field, val)), val)
- val = v + add_other_link(field, val)
+ val = v + add_other_links(field, val)
elif metadata['datatype'] == 'bool':
val = '{}'.format(
search_action_with_data(field, val, book_id, None), a(
diff --git a/src/calibre/gui2/book_details.py b/src/calibre/gui2/book_details.py
index 969bf0a03c..61c242d98b 100644
--- a/src/calibre/gui2/book_details.py
+++ b/src/calibre/gui2/book_details.py
@@ -319,11 +319,15 @@ def render_data(mi, use_roman_numbers=True, all_fields=False, pref_name='book_di
field_list = get_field_list(getattr(mi, 'field_metadata', field_metadata),
pref_name=pref_name, mi=mi)
field_list = [(x, all_fields or display) for x, display in field_list]
+ db, _ = db_for_mi(mi)
+ db = db.new_api
+ all_notes = db.get_all_items_that_have_notes()
+ all_notes = {fld: {db.get_item_name(fld, id_) for id_ in all_notes[fld]} for fld in all_notes.keys()}
return mi_to_html(
mi, field_list=field_list, use_roman_numbers=use_roman_numbers, rtl=is_rtl(),
rating_font=rating_font(), default_author_link=default_author_link(),
comments_heading_pos=gprefs['book_details_comments_heading_pos'], for_qt=True,
- vertical_fields=vertical_fields, show_links=show_links
+ vertical_fields=vertical_fields, show_links=show_links, all_notes=all_notes
)
# }}}
@@ -1291,16 +1295,17 @@ class BookDetails(DetailsLayout): # {{{
dt = data['type']
if dt == 'search':
field = data.get('field')
+ search_term(data['term'], data['value'])
+ elif dt == 'note':
+ field = data.get('field')
+ # It shouldn't be possible for the field to be invalid or the
+ # note not to exist, but ...
if field and db.field_supports_notes(field):
item_id = db.get_item_id(field, data['value'])
if item_id is not None and db.notes_for(field, item_id):
return self.show_notes(field, item_id)
- search_term(data['term'], data['value'])
elif dt == 'author':
url = data['url']
- item_id = db.get_item_id('authors', data['name'])
- if item_id is not None and db.notes_for('authors', item_id):
- return self.show_notes('authors', item_id)
if url == 'calibre':
search_term('authors', data['name'])
else: