Bug #1923942: virtual_libraries() doesn't list libraries with search expressions containing "marked:..."

This commit is contained in:
Charles Haley 2021-04-15 10:17:15 +01:00
parent 1c24a53865
commit 184c6976b9
4 changed files with 17 additions and 4 deletions

View File

@ -2208,13 +2208,13 @@ class Cache(object):
self._restore_annotations(book_id, annotations)
@read_api
def virtual_libraries_for_books(self, book_ids):
def virtual_libraries_for_books(self, book_ids, virtual_fields=None):
if self.vls_for_books_cache is None:
# Using a list is slightly faster than a set.
c = defaultdict(list)
libraries = self._pref('virtual_libraries', {})
for lib, expr in libraries.items():
for book in self._search(expr):
for book in self._search(expr, virtual_fields=virtual_fields):
c[book].append(lib)
self.vls_for_books_cache = {b:tuple(sorted(libs, key=sort_key)) for b, libs in c.items()}
if not book_ids:

View File

@ -258,6 +258,11 @@ def composite_getter(mi, field, dbref, book_id, cache, formatter, template_cache
def virtual_libraries_getter(dbref, book_id, cache):
'''
This method is deprecated because it doesn't (and can't) return virtual
library names when the VL search references marked books. It is replaced
by db.view.get_virtual_libraries_for_books()
'''
try:
return cache['virtual_libraries']
except KeyError:

View File

@ -232,6 +232,10 @@ class View(object):
ans = [':::'.join((adata[aid]['name'], adata[aid]['sort'], adata[aid]['link'])) for aid in ids if aid in adata]
return ':#:'.join(ans) if ans else default_value
def get_virtual_libraries_for_books(self, ids):
return self.cache.virtual_libraries_for_books(
ids, virtual_fields={'marked':MarkedVirtualField(self.marked_ids)})
def _do_sort(self, ids_to_sort, fields=(), subsort=False):
fields = [(sanitize_sort_field_name(self.field_metadata, x), bool(y)) for x, y in fields]
keys = self.field_metadata.sortable_field_keys()
@ -377,7 +381,9 @@ class View(object):
# This invalidates all searches in the cache even though the cache may
# be shared by multiple views. This is not ideal, but...
cmids = set(self.marked_ids)
self.cache.clear_search_caches(old_marked_ids | cmids)
changed_ids = old_marked_ids | cmids
self.cache.clear_search_caches(changed_ids)
self.refresh_ids(changed_ids)
if old_marked_ids != cmids:
for funcref in itervalues(self.marked_listeners):
func = funcref()

View File

@ -1714,7 +1714,9 @@ class BuiltinVirtualLibraries(BuiltinFormatterFunction):
def evaluate(self, formatter, kwargs, mi, locals_):
if hasattr(mi, '_proxy_metadata'):
return mi._proxy_metadata.virtual_libraries
from calibre.gui2.ui import get_gui
a = get_gui().current_db.data.get_virtual_libraries_for_books((mi.id,))
return ', '.join(a[mi.id])
return _('This function can be used only in the GUI')