Make :undo re-open all tabs closed by :tab-only
This changes the undo stack from a list of UndoEntry objects to a list of lists of UndoEntry objects, so groups of tabs can be added. Only :tab-only does that, but it's exposed by TabbedBrowser.close_tab as a keyword argument.
This commit is contained in:
parent
b1f1248a05
commit
3e8c84c018
@ -93,7 +93,7 @@ It is possible to run or bind multiple commands by separating them with `;;`.
|
|||||||
|<<tab-prev,tab-prev>>|Switch to the previous tab, or switch [count] tabs back.
|
|<<tab-prev,tab-prev>>|Switch to the previous tab, or switch [count] tabs back.
|
||||||
|<<tab-take,tab-take>>|Take a tab from another window.
|
|<<tab-take,tab-take>>|Take a tab from another window.
|
||||||
|<<unbind,unbind>>|Unbind a keychain.
|
|<<unbind,unbind>>|Unbind a keychain.
|
||||||
|<<undo,undo>>|Re-open a closed tab.
|
|<<undo,undo>>|Re-open the last closed tab or tabs.
|
||||||
|<<version,version>>|Show version information.
|
|<<version,version>>|Show version information.
|
||||||
|<<view-source,view-source>>|Show the source of the current page in a new tab.
|
|<<view-source,view-source>>|Show the source of the current page in a new tab.
|
||||||
|<<window-only,window-only>>|Close all windows except for the current one.
|
|<<window-only,window-only>>|Close all windows except for the current one.
|
||||||
@ -1065,7 +1065,7 @@ Unbind a keychain.
|
|||||||
|
|
||||||
[[undo]]
|
[[undo]]
|
||||||
=== undo
|
=== undo
|
||||||
Re-open a closed tab.
|
Re-open the last closed tab or tabs.
|
||||||
|
|
||||||
[[version]]
|
[[version]]
|
||||||
=== version
|
=== version
|
||||||
|
@ -968,13 +968,15 @@ class CommandDispatcher:
|
|||||||
prev=prev, next_=next_, force=True))
|
prev=prev, next_=next_, force=True))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
first_tab = True
|
||||||
for i, tab in enumerate(self._tabbed_browser.widgets()):
|
for i, tab in enumerate(self._tabbed_browser.widgets()):
|
||||||
if _to_close(i):
|
if _to_close(i):
|
||||||
self._tabbed_browser.close_tab(tab)
|
self._tabbed_browser.close_tab(tab, new_undo=first_tab)
|
||||||
|
first_tab = False
|
||||||
|
|
||||||
@cmdutils.register(instance='command-dispatcher', scope='window')
|
@cmdutils.register(instance='command-dispatcher', scope='window')
|
||||||
def undo(self):
|
def undo(self):
|
||||||
"""Re-open a closed tab."""
|
"""Re-open the last closed tab or tabs."""
|
||||||
try:
|
try:
|
||||||
self._tabbed_browser.undo()
|
self._tabbed_browser.undo()
|
||||||
except IndexError:
|
except IndexError:
|
||||||
|
@ -71,7 +71,7 @@ class TabbedBrowser(tabwidget.TabWidget):
|
|||||||
_tab_insert_idx_left: Where to insert a new tab with
|
_tab_insert_idx_left: Where to insert a new tab with
|
||||||
tabs.new_tab_position set to 'prev'.
|
tabs.new_tab_position set to 'prev'.
|
||||||
_tab_insert_idx_right: Same as above, for 'next'.
|
_tab_insert_idx_right: Same as above, for 'next'.
|
||||||
_undo_stack: List of UndoEntry objects of closed tabs.
|
_undo_stack: List of lists of UndoEntry objects of closed tabs.
|
||||||
shutting_down: Whether we're currently shutting down.
|
shutting_down: Whether we're currently shutting down.
|
||||||
_local_marks: Jump markers local to each page
|
_local_marks: Jump markers local to each page
|
||||||
_global_marks: Jump markers used across all pages
|
_global_marks: Jump markers used across all pages
|
||||||
@ -270,12 +270,13 @@ class TabbedBrowser(tabwidget.TabWidget):
|
|||||||
else:
|
else:
|
||||||
yes_action()
|
yes_action()
|
||||||
|
|
||||||
def close_tab(self, tab, *, add_undo=True):
|
def close_tab(self, tab, *, add_undo=True, new_undo=True):
|
||||||
"""Close a tab.
|
"""Close a tab.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
tab: The QWebView to be closed.
|
tab: The QWebView to be closed.
|
||||||
add_undo: Whether the tab close can be undone.
|
add_undo: Whether the tab close can be undone.
|
||||||
|
new_undo: Whether the undo entry should be a new item in the stack.
|
||||||
"""
|
"""
|
||||||
last_close = config.val.tabs.last_close
|
last_close = config.val.tabs.last_close
|
||||||
count = self.count()
|
count = self.count()
|
||||||
@ -283,7 +284,7 @@ class TabbedBrowser(tabwidget.TabWidget):
|
|||||||
if last_close == 'ignore' and count == 1:
|
if last_close == 'ignore' and count == 1:
|
||||||
return
|
return
|
||||||
|
|
||||||
self._remove_tab(tab, add_undo=add_undo)
|
self._remove_tab(tab, add_undo=add_undo, new_undo=new_undo)
|
||||||
|
|
||||||
if count == 1: # We just closed the last tab above.
|
if count == 1: # We just closed the last tab above.
|
||||||
if last_close == 'close':
|
if last_close == 'close':
|
||||||
@ -296,12 +297,13 @@ class TabbedBrowser(tabwidget.TabWidget):
|
|||||||
elif last_close == 'default-page':
|
elif last_close == 'default-page':
|
||||||
self.openurl(config.val.url.default_page, newtab=True)
|
self.openurl(config.val.url.default_page, newtab=True)
|
||||||
|
|
||||||
def _remove_tab(self, tab, *, add_undo=True, crashed=False):
|
def _remove_tab(self, tab, *, add_undo=True, new_undo=True, crashed=False):
|
||||||
"""Remove a tab from the tab list and delete it properly.
|
"""Remove a tab from the tab list and delete it properly.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
tab: The QWebView to be closed.
|
tab: The QWebView to be closed.
|
||||||
add_undo: Whether the tab close can be undone.
|
add_undo: Whether the tab close can be undone.
|
||||||
|
new_undo: Whether the undo entry should be a new item in the stack.
|
||||||
crashed: Whether we're closing a tab with crashed renderer process.
|
crashed: Whether we're closing a tab with crashed renderer process.
|
||||||
"""
|
"""
|
||||||
idx = self.indexOf(tab)
|
idx = self.indexOf(tab)
|
||||||
@ -336,7 +338,10 @@ class TabbedBrowser(tabwidget.TabWidget):
|
|||||||
else:
|
else:
|
||||||
entry = UndoEntry(tab.url(), history_data, idx,
|
entry = UndoEntry(tab.url(), history_data, idx,
|
||||||
tab.data.pinned)
|
tab.data.pinned)
|
||||||
self._undo_stack.append(entry)
|
if new_undo or not self._undo_stack:
|
||||||
|
self._undo_stack.append([entry])
|
||||||
|
else:
|
||||||
|
self._undo_stack[-1].append(entry)
|
||||||
|
|
||||||
tab.shutdown()
|
tab.shutdown()
|
||||||
self.removeTab(idx)
|
self.removeTab(idx)
|
||||||
@ -347,7 +352,7 @@ class TabbedBrowser(tabwidget.TabWidget):
|
|||||||
tab.deleteLater()
|
tab.deleteLater()
|
||||||
|
|
||||||
def undo(self):
|
def undo(self):
|
||||||
"""Undo removing of a tab."""
|
"""Undo removing of a tab or tabs."""
|
||||||
# Remove unused tab which may be created after the last tab is closed
|
# Remove unused tab which may be created after the last tab is closed
|
||||||
last_close = config.val.tabs.last_close
|
last_close = config.val.tabs.last_close
|
||||||
use_current_tab = False
|
use_current_tab = False
|
||||||
@ -366,16 +371,17 @@ class TabbedBrowser(tabwidget.TabWidget):
|
|||||||
use_current_tab = (only_one_tab_open and no_history and
|
use_current_tab = (only_one_tab_open and no_history and
|
||||||
last_close_url_used)
|
last_close_url_used)
|
||||||
|
|
||||||
entry = self._undo_stack.pop()
|
for entry in reversed(self._undo_stack.pop()):
|
||||||
|
if use_current_tab:
|
||||||
|
self.openurl(entry.url, newtab=False)
|
||||||
|
newtab = self.widget(0)
|
||||||
|
use_current_tab = False
|
||||||
|
else:
|
||||||
|
newtab = self.tabopen(entry.url, background=False,
|
||||||
|
idx=entry.index)
|
||||||
|
|
||||||
if use_current_tab:
|
newtab.history.deserialize(entry.history)
|
||||||
self.openurl(entry.url, newtab=False)
|
self.set_tab_pinned(newtab, entry.pinned)
|
||||||
newtab = self.widget(0)
|
|
||||||
else:
|
|
||||||
newtab = self.tabopen(entry.url, background=False, idx=entry.index)
|
|
||||||
|
|
||||||
newtab.history.deserialize(entry.history)
|
|
||||||
self.set_tab_pinned(newtab, entry.pinned)
|
|
||||||
|
|
||||||
@pyqtSlot('QUrl', bool)
|
@pyqtSlot('QUrl', bool)
|
||||||
def openurl(self, url, newtab):
|
def openurl(self, url, newtab):
|
||||||
|
@ -772,6 +772,18 @@ Feature: Tab management
|
|||||||
- data/numbers/2.txt
|
- data/numbers/2.txt
|
||||||
- data/numbers/3.txt
|
- data/numbers/3.txt
|
||||||
|
|
||||||
|
Scenario: Undo the closing of tabs using :tab-only
|
||||||
|
When I open data/numbers/1.txt
|
||||||
|
And I open data/numbers/2.txt in a new tab
|
||||||
|
And I open data/numbers/3.txt in a new tab
|
||||||
|
And I run :tab-focus 2
|
||||||
|
And I run :tab-only
|
||||||
|
And I run :undo
|
||||||
|
Then the following tabs should be open:
|
||||||
|
- data/numbers/1.txt (active)
|
||||||
|
- data/numbers/2.txt
|
||||||
|
- data/numbers/3.txt
|
||||||
|
|
||||||
# tabs.last_close
|
# tabs.last_close
|
||||||
|
|
||||||
# FIXME:qtwebengine
|
# FIXME:qtwebengine
|
||||||
|
Loading…
Reference in New Issue
Block a user