mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 02:34:06 -04:00
Merge branch 'master' of https://github.com/cbhaley/calibre
Fixes #2015719 [Minor bug: Sorting in user category editor](https://bugs.launchpad.net/calibre/+bug/2015719)
This commit is contained in:
commit
e653df9794
@ -2367,18 +2367,22 @@ class Cache:
|
|||||||
@read_api
|
@read_api
|
||||||
def get_all_link_maps_for_book(self, book_id):
|
def get_all_link_maps_for_book(self, book_id):
|
||||||
'''
|
'''
|
||||||
Returns all links for all fields referenced by book identified by book_id
|
Returns all links for all fields referenced by book identified by book_id.
|
||||||
|
If book_id is None or doesn't exist then the method returns {}.
|
||||||
|
|
||||||
Example: Assume author A has link X, author B has link Y, tag S has link
|
Example: Assume author A has link X, author B has link Y, tag S has link
|
||||||
F, and tag T has link G. IF book 1 has author A and tag T,
|
F, and tag T has link G. If book 1 has author A and tag T,
|
||||||
this method returns {'authors':{'A':'X'}, 'tags':{'T', 'G'}}
|
this method returns {'authors':{'A':'X'}, 'tags':{'T', 'G'}}
|
||||||
If book 2's author is neither A nor B and has no tags, this method returns {}
|
If book 2's author is neither A nor B and has no tags, this method returns {}
|
||||||
|
|
||||||
:param book_id: the book id in question.
|
:param book_id: the book id in question.
|
||||||
|
|
||||||
:return: {field: {field_value, link_value}, ... for all fields that have a non-empty link value for that book
|
:return: {field: {field_value, link_value}, ... for all fields with a field_value having a non-empty link value for that book
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
if not self.has_id(book_id):
|
||||||
|
# Works for book_id is None.
|
||||||
|
return {}
|
||||||
cached = self.link_maps_cache.get(book_id)
|
cached = self.link_maps_cache.get(book_id)
|
||||||
if cached is not None:
|
if cached is not None:
|
||||||
return cached
|
return cached
|
||||||
|
@ -183,14 +183,14 @@ def mi_to_html(
|
|||||||
else:
|
else:
|
||||||
if not metadata['is_multiple']:
|
if not metadata['is_multiple']:
|
||||||
val = '<a href="{}" title="{}">{}</a>'.format(
|
val = '<a href="{}" title="{}">{}</a>'.format(
|
||||||
search_action(field, val),
|
search_action(field, val, book_id=book_id),
|
||||||
_('Click to see books with {0}: {1}').format(metadata['name'], a(val)), p(val))
|
_('Click to see books with {0}: {1}').format(metadata['name'], a(val)), p(val))
|
||||||
else:
|
else:
|
||||||
all_vals = [v.strip()
|
all_vals = [v.strip()
|
||||||
for v in val.split(metadata['is_multiple']['cache_to_list']) if v.strip()]
|
for v in val.split(metadata['is_multiple']['cache_to_list']) if v.strip()]
|
||||||
if show_links:
|
if show_links:
|
||||||
links = ['<a href="{}" title="{}">{}</a>'.format(
|
links = ['<a href="{}" title="{}">{}</a>'.format(
|
||||||
search_action(field, x), _('Click to see books with {0}: {1}').format(
|
search_action(field, x, book_id=book_id), _('Click to see books with {0}: {1}').format(
|
||||||
metadata['name'], a(x)), p(x)) for x in all_vals]
|
metadata['name'], a(x)), p(x)) for x in all_vals]
|
||||||
else:
|
else:
|
||||||
links = all_vals
|
links = all_vals
|
||||||
@ -210,7 +210,7 @@ def mi_to_html(
|
|||||||
extra = '<br><span style="font-size:smaller">%s</span>'%(
|
extra = '<br><span style="font-size:smaller">%s</span>'%(
|
||||||
prepare_string_for_xml(durl))
|
prepare_string_for_xml(durl))
|
||||||
if show_links:
|
if show_links:
|
||||||
link = '<a href="{}" title="{}">{}</a>{}'.format(action(scheme, loc=loc),
|
link = '<a href="{}" title="{}">{}</a>{}'.format(action(scheme, book_id=book_id, loc=loc),
|
||||||
prepare_string_for_xml(path, True), pathstr, extra)
|
prepare_string_for_xml(path, True), pathstr, extra)
|
||||||
else:
|
else:
|
||||||
link = prepare_string_for_xml(path, True)
|
link = prepare_string_for_xml(path, True)
|
||||||
@ -238,7 +238,7 @@ def mi_to_html(
|
|||||||
if show_links:
|
if show_links:
|
||||||
links = [
|
links = [
|
||||||
'<a href="{}" title="{}:{}">{}</a>'.format(
|
'<a href="{}" title="{}:{}">{}</a>'.format(
|
||||||
action('identifier', url=url, name=namel, id_type=id_typ, value=id_val, field='identifiers', book_id=book_id),
|
action('identifier', book_id=book_id, url=url, name=namel, id_type=id_typ, value=id_val, field='identifiers'),
|
||||||
a(id_typ), a(id_val), p(namel))
|
a(id_typ), a(id_val), p(namel))
|
||||||
for namel, id_typ, id_val, url in urls]
|
for namel, id_typ, id_val, url in urls]
|
||||||
links = value_list(', ', links)
|
links = value_list(', ', links)
|
||||||
@ -266,7 +266,8 @@ def mi_to_html(
|
|||||||
else:
|
else:
|
||||||
aut = p(aut)
|
aut = p(aut)
|
||||||
if link:
|
if link:
|
||||||
val = '<a title="%s" href="%s">%s</a>'%(a(lt), action('author', url=link, name=aut, title=lt), aut)
|
val = '<a title="%s" href="%s">%s</a>'%(a(lt), action('author', book_id=book_id,
|
||||||
|
url=link, name=aut, title=lt), aut)
|
||||||
else:
|
else:
|
||||||
val = aut
|
val = aut
|
||||||
val += add_other_link('authors', aut)
|
val += add_other_link('authors', aut)
|
||||||
|
@ -391,6 +391,12 @@ def add_item_specific_entries(menu, data, book_info, copy_menu, search_menu):
|
|||||||
ac.data = ('authors', author, book_id)
|
ac.data = ('authors', author, book_id)
|
||||||
ac.setText(_('Remove %s from this book') % escape_for_menu(author))
|
ac.setText(_('Remove %s from this book') % escape_for_menu(author))
|
||||||
menu.addAction(ac)
|
menu.addAction(ac)
|
||||||
|
# See if we need to add a click associated link menu line for the author
|
||||||
|
link_map = get_gui().current_db.new_api.get_all_link_maps_for_book(data.get('book_id', None))
|
||||||
|
link = link_map.get("authors", {}).get(author, None)
|
||||||
|
if link:
|
||||||
|
menu.addAction(QIcon.ic('external-link'), _('Open associated link'),
|
||||||
|
lambda : book_info.link_clicked.emit(link))
|
||||||
elif dt in ('path', 'devpath'):
|
elif dt in ('path', 'devpath'):
|
||||||
path = data['loc']
|
path = data['loc']
|
||||||
ac = book_info.copy_link_action
|
ac = book_info.copy_link_action
|
||||||
@ -435,6 +441,12 @@ def add_item_specific_entries(menu, data, book_info, copy_menu, search_menu):
|
|||||||
ac.data = (field, remove_value, book_id)
|
ac.data = (field, remove_value, book_id)
|
||||||
ac.setText(_('Remove %s from this book') % escape_for_menu(remove_name or data.get('original_value') or value))
|
ac.setText(_('Remove %s from this book') % escape_for_menu(remove_name or data.get('original_value') or value))
|
||||||
menu.addAction(ac)
|
menu.addAction(ac)
|
||||||
|
# See if we need to add a click associated link menu line
|
||||||
|
link_map = get_gui().current_db.new_api.get_all_link_maps_for_book(data.get('book_id', None))
|
||||||
|
link = link_map.get(field, {}).get(value, None)
|
||||||
|
if link:
|
||||||
|
menu.addAction(QIcon.ic('external-link'), _('Open associated link'),
|
||||||
|
lambda : book_info.link_clicked.emit(link))
|
||||||
else:
|
else:
|
||||||
v = data.get('original_value') or data.get('value')
|
v = data.get('original_value') or data.get('value')
|
||||||
copy_menu.addAction(QIcon.ic('edit-copy.png'), _('The text: {}').format(v),
|
copy_menu.addAction(QIcon.ic('edit-copy.png'), _('The text: {}').format(v),
|
||||||
|
@ -126,6 +126,11 @@ class TagCategories(QDialog, Ui_TagCategories):
|
|||||||
def category_name_tuple(self, key, name):
|
def category_name_tuple(self, key, name):
|
||||||
return self.CategoryNameTuple(name, key)
|
return self.CategoryNameTuple(name, key)
|
||||||
|
|
||||||
|
def item_sort_key(self, v):
|
||||||
|
# Add the key so the order of identical items is predictable.
|
||||||
|
# The tab ensures that the values sort together regardless of key
|
||||||
|
return primary_sort_key(v.v + '\t ' + (v.k[1:] if v.k.startswith('#') else v.k))
|
||||||
|
|
||||||
def initialize_category_lists(self):
|
def initialize_category_lists(self):
|
||||||
cfb = self.category_filter_box
|
cfb = self.category_filter_box
|
||||||
current_cat_filter = (self.category_labels[cfb.currentIndex()]
|
current_cat_filter = (self.category_labels[cfb.currentIndex()]
|
||||||
@ -154,11 +159,9 @@ class TagCategories(QDialog, Ui_TagCategories):
|
|||||||
self.available_items[key] = av
|
self.available_items[key] = av
|
||||||
sorted_categories.append(self.category_name_tuple(key, self.all_items[key]['name']))
|
sorted_categories.append(self.category_name_tuple(key, self.all_items[key]['name']))
|
||||||
|
|
||||||
# Sort the items
|
self.sorted_items.sort(key=self.item_sort_key)
|
||||||
self.sorted_items.sort(key=lambda v: primary_sort_key(v.v + v.k))
|
sorted_categories.sort(key=lambda v: primary_sort_key(v.n))
|
||||||
|
|
||||||
# Fill in the category names with visible (not hidden) lookup keys
|
|
||||||
sorted_categories.sort(key=lambda v: primary_sort_key(v.n + v.k))
|
|
||||||
cfb.blockSignals(True)
|
cfb.blockSignals(True)
|
||||||
cfb.clear()
|
cfb.clear()
|
||||||
cfb.addItem('', '')
|
cfb.addItem('', '')
|
||||||
@ -227,7 +230,7 @@ class TagCategories(QDialog, Ui_TagCategories):
|
|||||||
ccn = self.current_cat_name
|
ccn = self.current_cat_name
|
||||||
if ccn:
|
if ccn:
|
||||||
self.applied_items = [v for v in self.user_categories[ccn]]
|
self.applied_items = [v for v in self.user_categories[ccn]]
|
||||||
self.applied_items.sort(key=lambda x:primary_sort_key(x.v + x.k))
|
self.applied_items.sort(key=self.item_sort_key)
|
||||||
else:
|
else:
|
||||||
self.applied_items = []
|
self.applied_items = []
|
||||||
self.applied_items_box.clear()
|
self.applied_items_box.clear()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user