Change in_tag_browser generation to not build the list of books if the tag browser categories haven't been restricted by 'find'. As the comment in the code says, this will improve performance while making in_tag_browser:true fail in extremely rare cases.

This commit is contained in:
Charles Haley 2022-09-20 10:19:01 +01:00
parent 616290b17e
commit b0bf2d23c8
2 changed files with 19 additions and 11 deletions

View File

@ -41,8 +41,11 @@ class InTagBrowserVirtualField:
self._ids = _ids
def iter_searchable_values(self, get_metadata, candidates, default_value=None):
# The returned value can be any string. For example it could be book_id
# as a string, but there is little point in spending the cpu cycles for
# that as no one will do a search like in_tag_browser:1544 (a book id)
for book_id in candidates:
yield str(book_id) if self._ids is None or book_id in self._ids else default_value, {book_id}
yield 'A' if self._ids is None or book_id in self._ids else default_value, {book_id}
def sort_keys_for_books(self, get_metadata, lang_map):
null = sys.maxsize

View File

@ -811,16 +811,21 @@ class TagsModel(QAbstractItemModel): # {{{
self.research_required.emit()
def set_in_tag_browser(self):
# rebuild the list even if there is no filter. This lets us support
# in_tag_browser:true or :false based on the displayed categories. It is
# a form of shorthand for searching for all the visible categories with
# category1:true OR category2:true etc. The cost: walking the tree and
# building the set for a case that will certainly rarely be different
# from all books because all books have authors.
# If the filter isn't set then don't build the list, improving
# performance significantly for large libraries or libraries with lots
# of categories. This means that in_tag_browser:true with no filter will
# return all books. This is incorrect in the rare case where the
# category list in the tag browser doesn't contain a category like
# authors that by definition matches all books because all books have an
# author. If really needed the user can work around this 'error' by
# clicking on the categories of interest with the connector set to 'or'.
if self.filter_categories_by:
id_set = set()
for x in (a for a in self.root_item.children if a.category_key != 'search' and not a.is_gst):
for t in x.child_tags():
id_set |= t.tag.id_set
else:
id_set = None
changed = self.db.data.get_in_tag_browser() != id_set
self.db.data.set_in_tag_browser(id_set)
return changed