Refactor :undo and save/restore history.
This commit is contained in:
parent
03e809a230
commit
4410536f69
@ -511,10 +511,9 @@ class CommandDispatcher:
|
||||
@cmdutils.register(instance='command-dispatcher')
|
||||
def undo(self):
|
||||
"""Re-open a closed tab (optionally skipping [count] closed tabs)."""
|
||||
url_stack = objreg.get('url-stack', None)
|
||||
if url_stack:
|
||||
objreg.get('tabbed-browser').tabopen(url_stack.pop())
|
||||
else:
|
||||
try:
|
||||
objreg.get('tabbed-browser').undo()
|
||||
except IndexError:
|
||||
raise cmdexc.CommandError("Nothing to undo!")
|
||||
|
||||
@cmdutils.register(instance='command-dispatcher')
|
||||
|
@ -32,7 +32,8 @@ import sys
|
||||
import operator
|
||||
from distutils.version import StrictVersion as Version
|
||||
|
||||
from PyQt5.QtCore import QEventLoop, qVersion
|
||||
from PyQt5.QtCore import (qVersion, QEventLoop, QDataStream, QByteArray,
|
||||
QIODevice)
|
||||
|
||||
|
||||
MAXVALS = {
|
||||
@ -128,6 +129,36 @@ def ensure_valid(obj):
|
||||
raise QtValueError(obj)
|
||||
|
||||
|
||||
def _check_qdatastream(stream):
|
||||
"""Check the status of a QDataStream and raise IOError if it's not ok."""
|
||||
status_to_str = {
|
||||
QDataStream.Ok: "The data stream is operating normally.",
|
||||
QDataStream.ReadPastEnd: ("The data stream has read past the end of "
|
||||
"the data in the underlying device."),
|
||||
QDataStream.ReadCorruptData: "The data stream has read corrupt data.",
|
||||
QDataStream.WriteFailed: ("The data stream cannot write to the "
|
||||
"underlying device."),
|
||||
}
|
||||
if stream.status() != QDataStream.Ok:
|
||||
raise IOError(status_to_str[stream.status()])
|
||||
|
||||
|
||||
def serialize(obj):
|
||||
"""Serialize an object into a QByteArray."""
|
||||
data = QByteArray()
|
||||
stream = QDataStream(data, QIODevice.WriteOnly)
|
||||
stream << obj
|
||||
_check_qdatastream(stream)
|
||||
return data
|
||||
|
||||
|
||||
def deserialize(data, obj):
|
||||
"""Deserialize an object from a QByteArray."""
|
||||
stream = QDataStream(data, QIODevice.ReadOnly)
|
||||
stream >> obj
|
||||
_check_qdatastream(stream)
|
||||
|
||||
|
||||
class QtValueError(ValueError):
|
||||
|
||||
"""Exception which gets raised by ensure_valid."""
|
||||
|
@ -20,6 +20,7 @@
|
||||
"""The main tabbed browser widget."""
|
||||
|
||||
import functools
|
||||
import collections
|
||||
|
||||
from PyQt5.QtWidgets import QSizePolicy
|
||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QSize, QTimer, QUrl
|
||||
@ -34,6 +35,9 @@ from qutebrowser.browser import signalfilter, commands
|
||||
from qutebrowser.utils import log, message, usertypes, utils, qtutils, objreg
|
||||
|
||||
|
||||
UndoEntry = collections.namedtuple('UndoEntry', ['url', 'history'])
|
||||
|
||||
|
||||
class TabbedBrowser(tabwidget.TabWidget):
|
||||
|
||||
"""A TabWidget with QWebViews inside.
|
||||
@ -53,7 +57,7 @@ class TabbedBrowser(tabwidget.TabWidget):
|
||||
_tab_insert_idx_left: Where to insert a new tab with
|
||||
tabbar -> new-tab-position set to 'left'.
|
||||
_tab_insert_idx_right: Same as above, for 'right'.
|
||||
_url_stack: Stack of URLs of closed tabs.
|
||||
_undo_stack: List of UndoEntry namedtuples of closed tabs.
|
||||
|
||||
Signals:
|
||||
cur_progress: Progress of the current tab changed (loadProgress).
|
||||
@ -102,8 +106,7 @@ class TabbedBrowser(tabwidget.TabWidget):
|
||||
self.cur_load_started.connect(self.on_cur_load_started)
|
||||
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
||||
self._tabs = []
|
||||
self._url_stack = []
|
||||
objreg.register('url-stack', self._url_stack)
|
||||
self._undo_stack = []
|
||||
self._filter = signalfilter.SignalFilter(self)
|
||||
dispatcher = commands.CommandDispatcher()
|
||||
objreg.register('command-dispatcher', dispatcher)
|
||||
@ -244,12 +247,20 @@ class TabbedBrowser(tabwidget.TabWidget):
|
||||
objreg.delete('last-focused-tab')
|
||||
if not tab.cur_url.isEmpty():
|
||||
qtutils.ensure_valid(tab.cur_url)
|
||||
self._url_stack.append(tab.cur_url)
|
||||
history_data = qtutils.serialize(tab.history())
|
||||
entry = UndoEntry(tab.cur_url, history_data)
|
||||
self._undo_stack.append(entry)
|
||||
tab.shutdown()
|
||||
self._tabs.remove(tab)
|
||||
self.removeTab(idx)
|
||||
tab.deleteLater()
|
||||
|
||||
def undo(self):
|
||||
"""Undo removing of a tab."""
|
||||
url, history_data = self._undo_stack.pop()
|
||||
newtab = self.tabopen(url)
|
||||
qtutils.deserialize(history_data, newtab.history())
|
||||
|
||||
@pyqtSlot('QUrl', bool)
|
||||
def openurl(self, url, newtab):
|
||||
"""Open a URL, used as a slot.
|
||||
|
Loading…
Reference in New Issue
Block a user