From e6c02ec611f26bf8a9736561f7439ecbce57d4cf Mon Sep 17 00:00:00 2001 From: Charles Haley Date: Sat, 17 Oct 2020 12:50:46 +0100 Subject: [PATCH] Make the tag browser expand and collapse menu items consistent. 1) add separate lines to expand item and expand item and children 2) add collapse lines for all parent nodes, not just the immediate parent and the category root --- src/calibre/gui2/tag_browser/view.py | 88 ++++++++++++++++------------ 1 file changed, 49 insertions(+), 39 deletions(-) diff --git a/src/calibre/gui2/tag_browser/view.py b/src/calibre/gui2/tag_browser/view.py index 7ec1513ca7..c4e6e5c917 100644 --- a/src/calibre/gui2/tag_browser/view.py +++ b/src/calibre/gui2/tag_browser/view.py @@ -806,19 +806,6 @@ class TagsView(QTreeView): # {{{ _('Manage User categories'), partial(self.context_menu_handler, action='manage_categories', category=None)) - - node_name = tag_item.tag.name - parent = tag_item.parent - if parent.type != TagTreeItem.ROOT: - # We have an internal node. Find its immediate parent - parent_index = self._model.parent(index) - parent_node = parent - parent_name = parent.tag.name - else: - # We have a top-level node. - parent_index = index - parent_node = tag_item - parent_name = tag_item.name if self.hidden_categories: if not self.context_menu.isEmpty(): self.context_menu.addSeparator() @@ -850,47 +837,70 @@ class TagsView(QTreeView): # {{{ da.setToolTip('*') pa.setToolTip('*') + # Add expand menu items + node_name = self._model.get_node(index).tag.name self.context_menu.addSeparator() - if index.isValid() and self.model().rowCount(index) > 0: - if self.isExpanded(index): - self.context_menu.addAction(_("Collapse {0}").format(node_name), - partial(self.collapse_node, index)) - else: - self.context_menu.addAction(_('Expand {0}').format(node_name), - partial(self.expand_node_and_descendants, index)) - if parent_index is not None and parent_index != index: - if self.isExpanded(parent_index): - # Don't bother to collapse if it isn't expanded - self.context_menu.addAction(_("Collapse {0}").format(parent_name), - partial(self.collapse_node, parent_index)) - if parent_node.parent.type != TagTreeItem.ROOT: - # Add the top level node if the current parent is an internal node - while parent_node.parent.type != TagTreeItem.ROOT: - parent_node = parent_node.parent - idx = self._model.index_for_category(parent_node.category_key) - self.context_menu.addAction(_("Collapse {0}").format(parent_node.name), - partial(self.collapse_node, idx)) + if self.has_children(index) and not self.isExpanded(index): + self.context_menu.addAction(_('Expand {0}').format(node_name), + partial(self.expand, index)) + if self.has_unexpanded_children(index): + self.context_menu.addAction(_('Expand {0} and all children').format(node_name), + partial(self.expand_node_and_children, index)) + + # Add menu items to collapse parent nodes + idx = index + paths = [] + while True: + # First walk up the node tree getting the displayed names of + # expanded parent nodes + node = self._model.get_node(idx) + if node.type == TagTreeItem.ROOT: + break + if self.has_children(idx): + # leaf nodes don't have children so can't be expanded. + paths.append((node.tag.name, idx)) + idx = self._model.parent(idx) + for p in paths: + # Now add the menu items + self.context_menu.addAction(_("Collapse {0}").format(p[0]), + partial(self.collapse_node, p[1])) self.context_menu.addAction(_('Collapse all'), self.collapseAll) if not self.context_menu.isEmpty(): self.context_menu.popup(self.mapToGlobal(point)) return True + def has_children(self, idx): + return self.model().rowCount(idx) > 0 + + def collapse_node_and_children(self, idx): + self.collapse(idx) + for r in range(self.model().rowCount(idx)): + self.collapse_node_and_children(idx.child(r, 0)) + def collapse_node(self, idx): - def collapse_node_and_children(idx): - self.collapse(idx) - for r in range(self.model().rowCount(idx)): - collapse_node_and_children(idx.child(r, 0)) - collapse_node_and_children(idx) + if not idx.isValid(): + return + self.collapse_node_and_children(idx) self.setCurrentIndex(idx) self.scrollTo(idx) - def expand_node_and_descendants(self, index): + def expand_node_and_children(self, index): if not index.isValid(): return self.expand(index) for r in range(self.model().rowCount(index)): - self.expand_node_and_descendants(index.child(r, 0)) + self.expand_node_and_children(index.child(r, 0)) + + def has_unexpanded_children(self, index): + if not index.isValid(): + return + if self.has_children(index) and not self.isExpanded(index): + return True + for r in range(self.model().rowCount(index)): + if self.has_unexpanded_children(index.child(r, 0)): + return True + return False def collapse_menu_hovered(self, action): tip = action.toolTip()