diff --git a/src/calibre/gui2/tag_browser/model.py b/src/calibre/gui2/tag_browser/model.py index dbe071378a..6c36c9d22a 100644 --- a/src/calibre/gui2/tag_browser/model.py +++ b/src/calibre/gui2/tag_browser/model.py @@ -1204,10 +1204,13 @@ class TagsModel(QAbstractItemModel): # {{{ data[category] = [t for t in data[category] if lower(t.name).find(filter_by) >= 0] - # Build a dict of the keys that have data + # Build a dict of the keys that have data. + # Always add user categories so that the constructed hierarchy works. + # This means that empty categories will be displayed unless the 'hide + # empty categories' box is checked. tb_categories = self.db.field_metadata for category in tb_categories: - if category in data: # The search category can come and go + if category in data or category.startswith('@'): self.categories[category] = tb_categories[category]['name'] # Now build the list of fields in display order. A lot of this is to diff --git a/src/calibre/gui2/tag_browser/view.py b/src/calibre/gui2/tag_browser/view.py index 56f7c34573..4cf85a0d9a 100644 --- a/src/calibre/gui2/tag_browser/view.py +++ b/src/calibre/gui2/tag_browser/view.py @@ -976,8 +976,12 @@ class TagsView(QTreeView): # {{{ # Hide/Show/Restore categories self.context_menu.addSeparator() - self.context_menu.addAction(_('Hide category %s') % category.replace('&', '&&'), - partial(self.context_menu_handler, action='hide', + # Because of the strange way hierarchy works in user categories + # where child nodes actually exist we must limit hiding to top- + # level categories, which will hide that category and children + if not key.startswith('@') or '.' not in key: + self.context_menu.addAction(_('Hide category %s') % category.replace('&', '&&'), + partial(self.context_menu_handler, action='hide', category=key)).setIcon(QIcon.ic('minus.png')) add_show_hidden_categories()