From 8d5840afc65788e7cc0fe9cbf7de67908464c5fb Mon Sep 17 00:00:00 2001 From: Charles Haley Date: Sun, 26 Feb 2023 16:37:56 +0000 Subject: [PATCH] Enhancement #2006979: Hierarchical search menu in Additional Restrictions --- src/calibre/gui2/search_box.py | 37 ++++++++++++-------- src/calibre/gui2/search_restriction_mixin.py | 32 ++++++++--------- 2 files changed, 37 insertions(+), 32 deletions(-) diff --git a/src/calibre/gui2/search_box.py b/src/calibre/gui2/search_box.py index 6070a5fe7a..71a77a00e0 100644 --- a/src/calibre/gui2/search_box.py +++ b/src/calibre/gui2/search_box.py @@ -439,17 +439,12 @@ class SavedSearchBoxMixin: # {{{ def init_saved_seach_box_mixin(self): pass - def populate_add_saved_search_menu(self, to_menu): - m = to_menu - m.clear() - m.clear() - m.addAction(QIcon.ic('search_add_saved.png'), _('Add Saved search'), self.add_saved_search) - m.addAction(QIcon.ic('search_copy_saved.png'), _('Get Saved search expression'), - self.get_saved_search_text) - m.addAction(QIcon.ic('folder_saved_search.png'), _('Manage Saved searches'), - partial(self.do_saved_search_edit, None)) - m.addSeparator() - db = self.current_db + def add_saved_searches_to_menu(self, menu, db, add_action_func=None): + def add_action(current_menu, whole_name, last_component, func=None): + if add_action_func is None: + return current_menu.addAction(last_component, func) + return add_action_func(current_menu, whole_name, last_component) + folder_icon = QIcon.ic('folder_saved_search.png') search_icon = QIcon.ic('search.png') use_hierarchy = 'search' in db.new_api.pref('categories_using_hierarchy', []) @@ -459,7 +454,7 @@ class SavedSearchBoxMixin: # {{{ components = tuple(n.strip() for n in name.split('.')) hierarchy = components[:-1] last = components[-1] - current_menu = m + current_menu = menu # Walk the hierarchy, creating submenus as needed for i,c in enumerate(hierarchy, start=1): hierarchical_prefix = '.'.join(hierarchy[:i]) @@ -469,10 +464,22 @@ class SavedSearchBoxMixin: # {{{ submenus[hierarchical_prefix] = current_menu else: current_menu = submenus[hierarchical_prefix] - ac = current_menu.addAction(last, partial(self.search.set_search_string, 'search:"='+name+'"')) + ac = add_action(current_menu, name, last, partial(self.search.set_search_string, 'search:"='+name+'"')) else: - ac = m.addAction(name, partial(self.search.set_search_string, 'search:"='+name+'"')) - ac.setIcon(search_icon) + ac = add_action(current_menu, name, name, partial(self.search.set_search_string, 'search:"='+name+'"')) + if ac.icon().isNull(): + ac.setIcon(search_icon) + + def populate_add_saved_search_menu(self, to_menu): + m = to_menu + m.clear() + m.addAction(QIcon.ic('search_add_saved.png'), _('Add Saved search'), self.add_saved_search) + m.addAction(QIcon.ic('search_copy_saved.png'), _('Get Saved search expression'), + self.get_saved_search_text) + m.addAction(QIcon.ic('folder_saved_search.png'), _('Manage Saved searches'), + partial(self.do_saved_search_edit, None)) + m.addSeparator() + self.add_saved_searches_to_menu(m, self.current_db) def saved_searches_changed(self, set_restriction=None, recount=True): self.build_search_restriction_list() diff --git a/src/calibre/gui2/search_restriction_mixin.py b/src/calibre/gui2/search_restriction_mixin.py index 5f35b92cbd..b03524885a 100644 --- a/src/calibre/gui2/search_restriction_mixin.py +++ b/src/calibre/gui2/search_restriction_mixin.py @@ -547,7 +547,6 @@ class SearchRestrictionMixin: def build_search_restriction_list(self): self.search_restriction_list_built = True - from calibre.gui2.ui import get_gui m = self.ar_menu m.clear() @@ -562,26 +561,25 @@ class SearchRestrictionMixin: current_restriction = self.library_view.model().db.data.get_search_restriction_name() m.setIcon(self.checked if current_restriction else self.empty) - def add_action(txt, index): - self.search_restriction.addItem(txt) - txt = self._trim_restriction_name(txt) - if txt == current_restriction: - a = m.addAction(self.checked, txt if txt else self.no_restriction) + dex = 0 + def add_action(current_menu, name, last): + nonlocal dex + self.search_restriction.addItem(name) + txt = self._trim_restriction_name(last) + if name == current_restriction: + a = current_menu.addAction(self.checked, txt if txt else self.no_restriction) else: - a = m.addAction(self.empty, txt if txt else self.no_restriction) + a = current_menu.addAction(txt if txt else self.no_restriction) a.triggered.connect(partial(self.search_restriction_triggered, - action=a, index=index)) + action=a, index=dex)) + dex += 1 + return a - add_action('', 0) - add_action(_('*current search'), 1) - dex = 2 + add_action(m, '', '') + add_action(m, _('*current search'), _('*current search')) if current_restriction_text: - add_action(current_restriction_text, 2) - dex += 1 - - for n in sorted(get_gui().current_db.saved_search_names(), key=sort_key): - add_action(n, dex) - dex += 1 + add_action(m, current_restriction_text) + self.add_saved_searches_to_menu(m, self.library_view.model().db, add_action) def search_restriction_triggered(self, action=None, index=None): self.search_restriction.setCurrentIndex(index)