Skip to content

Commit

Permalink
Handle tab title updates while loading hidden tabs from a session
Browse files Browse the repository at this point in the history
This is the third case where errors have been raised from update_tab_titles()
due to a mismatch between the tab widget and node tree:

1. on startup when the tabs are being added to the widget but the tree hasn't
   grown yet - identified with heuristic
2. when hiding and showing tabs - changed logic to not fire updates
   mid-operation
3. when shutting down tabs get removed from the widget before they are removed
   from the tree - changed logic to not fire updates mid-operation

Now there is a fourth issue: loading a session with hidden tabs. In this case
tabs will be in the widget but not in the rendered tree, because that doesn't
include hidden nodes.

I'm using "all the URLs are empty" as a proxy for "a session is loading into
this window". That combined with there being a hidden tab in the tree should
hopefully be a good enough heuristic for this case. Although it would be good
to check with 100% certainty that a session was being loaded. Or just
having something to see if the current window was still being
initialized would do it, as sessions are always loaded into new windows.

I've refactored the logic in this method so that we are matching on exact tab
value, instead of having two lists and assuming the indexes are going to line
up. This way seems a bit more deliberate.
  • Loading branch information
toofar committed Jan 6, 2024
1 parent 8aa88b8 commit 3ec2000
Showing 1 changed file with 59 additions and 15 deletions.
74 changes: 59 additions & 15 deletions qutebrowser/mainwindow/treetabwidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,27 +38,71 @@ def get_tab_fields(self, idx):
return fields

rendered_tree = self.tree_root.render()
tab = self.widget(idx)
found = [
prefix
for prefix, node in rendered_tree
if node.value == tab
]

if len(found) == 1:
# we remove the first two chars because every tab is child of tree
# root and that gets rendered as well
fields['tree'] = found[0][2:]
fields['collapsed'] = '[...] ' if tab.node.collapsed else ''
return fields

# We are getting called with an index into the tab bar. If we have a
# different amount of nodes in the tree than the tab bar that
# indicates a logic error.
difference = len(rendered_tree) - 1 - self.count()
if difference != 0:
tabs = [str(self.widget(idx)) for idx in range(self.count())]
# Beyond here we have a mismatch between the tab widget and the tree.
# Try to identify known situations where this happens precisely and
# handle them gracefully. Blow up on unknown situations so we don't
# miss them.

# Just sanity checking, we haven't seen this yet.
assert len(found) == 0, (
"Found multiple tree nodes with the same tab as value: tab={tab}"
)

# Having more tabs in the widget when loading a session with a
# collapsed group in is a known case. Check for it with a heuristic
# (for now) and assert if that doesn't look like that's how we got
# here.
all_nodes = self.tree_root.traverse()
node = [n for n in all_nodes if n.value == tab][0]
is_hidden = any(n.collapsed for n in node.path)

tabs = [str(self.widget(idx)) for idx in range(self.count())]
difference = len(rendered_tree) - 1 - len(tabs)
# empty_urls here is a proxy for "there is a session being loaded into
# this window"
empty_urls = all(
[self.widget(idx).url().toString() == "" for idx in range(self.count())]
)
if empty_urls and is_hidden:
# All tabs will be added to the tab widget during session load
# and they will only be removed later when the widget is
# updated from the tree. Meanwhile, if we get here we'll have
# hidden tabs present in the widget but absent from the node.
# To detect this situation more clearly we could do something like
# have a is_starting_up or is_loading_session attribute on the
# tabwidget/tabbbedbrowser. Or have the session manager add all
# nodes to the tree uncollapsed initially and then go through and
# collapse them.
log.misc.vdebug(
"get_tab_fields() called with different amount of tabs in "
f"widget vs in the tree: difference={difference} "
f"tree={rendered_tree[1:]} tabs={tabs}"
)
else:
# If we get here then we have another case to investigate.
assert difference == 0, (
"Different amount of nodes in tree than widget. "
f"difference={difference} tree={rendered_tree[1:]} tabs={tabs}"
)

# we remove the first two chars because every tab is child of tree
# root and that gets rendered as well
pre, _ = rendered_tree[idx+1]
tree_prefix = pre[2:]
fields['tree'] = tree_prefix

tab = self.widget(idx)
fields['collapsed'] = '[...] ' if tab.node.collapsed else ''

# Return dummy entries for now. Once we finish whatever operation is
# causing the current irregularity we should get proper values.
fields["tree"] = ""
fields["collapsed"] = ""
return fields

def update_tree_tab_positions(self):
Expand Down

0 comments on commit 3ec2000

Please sign in to comment.