Merge branch 'EliteTK-history-clear'
This commit is contained in:
commit
a5a4c17b1f
@ -34,6 +34,7 @@ Added
|
||||
pressed. This can be turned off using `:set ui keyhint-blacklist *`.
|
||||
- New `hints -> auto-follow-timeout` setting to ignore keypresses after
|
||||
following a hint when filtering in number mode.
|
||||
- New `:history-clear` command to clear the entire history
|
||||
|
||||
Changed
|
||||
~~~~~~~
|
||||
|
@ -188,6 +188,7 @@ Contributors, sorted by the number of commits in descending order:
|
||||
* sbinix
|
||||
* neeasade
|
||||
* jnphilipp
|
||||
* Tomasz Kramkowski
|
||||
* Tobias Patzl
|
||||
* Stefan Tatschner
|
||||
* Peter Michely
|
||||
@ -211,7 +212,6 @@ Contributors, sorted by the number of commits in descending order:
|
||||
* evan
|
||||
* dylan araps
|
||||
* Xitian9
|
||||
* Tomasz Kramkowski
|
||||
* Tomas Orsava
|
||||
* Tobias Werth
|
||||
* Tim Harder
|
||||
|
@ -26,6 +26,7 @@
|
||||
|<<fullscreen,fullscreen>>|Toggle fullscreen mode.
|
||||
|<<help,help>>|Show help about a command or setting.
|
||||
|<<hint,hint>>|Start hinting.
|
||||
|<<history-clear,history-clear>>|Clear all history entries.
|
||||
|<<home,home>>|Open main startpage in current tab.
|
||||
|<<inspector,inspector>>|Toggle the web inspector.
|
||||
|<<jseval,jseval>>|Evaluate a JavaScript string.
|
||||
@ -356,6 +357,10 @@ Start hinting.
|
||||
==== note
|
||||
* This command does not split arguments after the last argument and handles quotes literally.
|
||||
|
||||
[[history-clear]]
|
||||
=== history-clear
|
||||
Clear all history entries.
|
||||
|
||||
[[home]]
|
||||
=== home
|
||||
Open main startpage in current tab.
|
||||
|
@ -25,6 +25,7 @@ import collections
|
||||
from PyQt5.QtCore import pyqtSignal, QUrl
|
||||
from PyQt5.QtWebKit import QWebHistoryInterface
|
||||
|
||||
from qutebrowser.commands import cmdutils
|
||||
from qutebrowser.utils import utils, objreg, standarddir, log
|
||||
from qutebrowser.config import config
|
||||
from qutebrowser.misc import lineparser
|
||||
@ -72,10 +73,12 @@ class WebHistory(QWebHistoryInterface):
|
||||
arg: The new HistoryEntry.
|
||||
item_added: Emitted after a new HistoryEntry is added.
|
||||
arg: The new HistoryEntry.
|
||||
cleared: Emitted after the history is cleared.
|
||||
"""
|
||||
|
||||
add_completion_item = pyqtSignal(HistoryEntry)
|
||||
item_added = pyqtSignal(HistoryEntry)
|
||||
cleared = pyqtSignal()
|
||||
async_read_done = pyqtSignal()
|
||||
|
||||
def __init__(self, parent=None):
|
||||
@ -169,6 +172,16 @@ class WebHistory(QWebHistoryInterface):
|
||||
self._lineparser.save()
|
||||
self._saved_count = len(self._new_history)
|
||||
|
||||
@cmdutils.register(name='history-clear', instance='web-history')
|
||||
def clear(self):
|
||||
"""Clear all history entries."""
|
||||
self._lineparser.clear()
|
||||
self._history_dict.clear()
|
||||
self._temp_history.clear()
|
||||
self._new_history.clear()
|
||||
self._saved_count = 0
|
||||
self.cleared.emit()
|
||||
|
||||
def addHistoryEntry(self, url_string):
|
||||
"""Called by WebKit when an URL should be added to the history.
|
||||
|
||||
|
@ -76,6 +76,7 @@ class UrlCompletionModel(base.BaseCompletionModel):
|
||||
for entry in history:
|
||||
self._add_history_entry(entry)
|
||||
self._history.add_completion_item.connect(self.on_history_item_added)
|
||||
self._history.cleared.connect(self.on_history_cleared)
|
||||
|
||||
objreg.get('config').changed.connect(self.reformat_timestamps)
|
||||
|
||||
@ -130,6 +131,10 @@ class UrlCompletionModel(base.BaseCompletionModel):
|
||||
else:
|
||||
self._add_history_entry(entry)
|
||||
|
||||
@pyqtSlot()
|
||||
def on_history_cleared(self):
|
||||
self._history_cat.removeRows(0, self._history_cat.rowCount())
|
||||
|
||||
def _remove_item(self, data, category, column):
|
||||
"""Helper function for on_quickmark_removed and on_bookmark_removed.
|
||||
|
||||
|
@ -114,6 +114,8 @@ class BaseLineParser(QObject):
|
||||
fp: A file object to write the data to.
|
||||
data: The data to write.
|
||||
"""
|
||||
if not data:
|
||||
return
|
||||
if self._binary:
|
||||
fp.write(b'\n'.join(data))
|
||||
fp.write(b'\n')
|
||||
@ -125,6 +127,10 @@ class BaseLineParser(QObject):
|
||||
"""Save the history to disk."""
|
||||
raise NotImplementedError
|
||||
|
||||
def clear(self):
|
||||
"""Clear the contents of the file."""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class AppendLineParser(BaseLineParser):
|
||||
|
||||
@ -183,6 +189,15 @@ class AppendLineParser(BaseLineParser):
|
||||
self.new_data = []
|
||||
self._after_save()
|
||||
|
||||
def clear(self):
|
||||
do_save = self._prepare_save()
|
||||
if not do_save:
|
||||
return
|
||||
with self._open('w'):
|
||||
pass
|
||||
self.new_data = []
|
||||
self._after_save()
|
||||
|
||||
|
||||
class LineParser(BaseLineParser):
|
||||
|
||||
@ -237,6 +252,10 @@ class LineParser(BaseLineParser):
|
||||
self._opened = False
|
||||
self._after_save()
|
||||
|
||||
def clear(self):
|
||||
self.data = []
|
||||
self.save()
|
||||
|
||||
|
||||
class LimitLineParser(LineParser):
|
||||
|
||||
|
@ -57,6 +57,9 @@ class LineparserSaveStub(lineparser.BaseLineParser):
|
||||
def save(self):
|
||||
self.saved = self.data
|
||||
|
||||
def clear(self):
|
||||
pass
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.data)
|
||||
|
||||
|
@ -19,80 +19,11 @@
|
||||
|
||||
"""Tests for qutebrowser.misc.lineparser."""
|
||||
|
||||
import io
|
||||
import os
|
||||
|
||||
import pytest
|
||||
|
||||
from qutebrowser.misc import lineparser as lineparsermod
|
||||
|
||||
|
||||
class LineParserMixin:
|
||||
|
||||
"""A wrapper over lineparser.BaseLineParser to make it testable."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self._data = None
|
||||
self._test_save_prepared = False
|
||||
|
||||
def _open(self, mode):
|
||||
"""Override _open to use StringIO/BytesIO instead of a real file."""
|
||||
if mode not in 'rwa':
|
||||
raise ValueError("Unknown mode {!r}!".format(mode))
|
||||
if self._test_save_prepared:
|
||||
self._test_save_prepared = False
|
||||
elif mode != 'r':
|
||||
raise ValueError("Doing unprepared save!")
|
||||
|
||||
if mode in 'ar' and self._data is not None:
|
||||
prev_val = self._data
|
||||
else:
|
||||
prev_val = None
|
||||
|
||||
if self._binary:
|
||||
fobj = io.BytesIO(prev_val)
|
||||
else:
|
||||
fobj = io.StringIO(prev_val)
|
||||
|
||||
if mode == 'a':
|
||||
fobj.seek(0, os.SEEK_END)
|
||||
return fobj
|
||||
|
||||
def _write(self, fp, data):
|
||||
"""Extend _write to get the data after writing it."""
|
||||
super()._write(fp, data)
|
||||
self._data = fp.getvalue()
|
||||
|
||||
def _prepare_save(self):
|
||||
"""Keep track if _prepare_save has been called."""
|
||||
self._test_save_prepared = True
|
||||
return True
|
||||
|
||||
|
||||
class AppendLineParserTestable(LineParserMixin,
|
||||
lineparsermod.AppendLineParser):
|
||||
|
||||
"""Wrapper over AppendLineParser to make it testable."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class LineParserTestable(LineParserMixin, lineparsermod.LineParser):
|
||||
|
||||
"""Wrapper over LineParser to make it testable."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class LimitLineParserTestable(LineParserMixin,
|
||||
lineparsermod.LimitLineParser):
|
||||
|
||||
"""Wrapper over LimitLineParser to make it testable."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class TestBaseLineParser:
|
||||
|
||||
"""Tests for BaseLineParser."""
|
||||
@ -122,6 +53,24 @@ class TestBaseLineParser:
|
||||
os_mock.makedirs.assert_called_with(self.CONFDIR, 0o755)
|
||||
|
||||
|
||||
class TestLineParser:
|
||||
|
||||
@pytest.fixture
|
||||
def lineparser(self, tmpdir):
|
||||
"""Fixture to get a LineParser for tests."""
|
||||
lp = lineparsermod.LineParser(str(tmpdir), 'file')
|
||||
lp.save()
|
||||
return lp
|
||||
|
||||
def test_clear(self, tmpdir, lineparser):
|
||||
lineparser.data = ['one', 'two']
|
||||
lineparser.save()
|
||||
assert (tmpdir / 'file').read() == 'one\ntwo\n'
|
||||
lineparser.clear()
|
||||
assert not lineparser.data
|
||||
assert (tmpdir / 'file').read() == ''
|
||||
|
||||
|
||||
class TestAppendLineParser:
|
||||
|
||||
"""Tests for AppendLineParser."""
|
||||
@ -129,9 +78,9 @@ class TestAppendLineParser:
|
||||
BASE_DATA = ['old data 1', 'old data 2']
|
||||
|
||||
@pytest.fixture
|
||||
def lineparser(self):
|
||||
def lineparser(self, tmpdir):
|
||||
"""Fixture to get an AppendLineParser for tests."""
|
||||
lp = AppendLineParserTestable('this really', 'does not matter')
|
||||
lp = lineparsermod.AppendLineParser(str(tmpdir), 'file')
|
||||
lp.new_data = self.BASE_DATA
|
||||
lp.save()
|
||||
return lp
|
||||
@ -140,12 +89,23 @@ class TestAppendLineParser:
|
||||
"""Get the expected data with newlines."""
|
||||
return '\n'.join(self.BASE_DATA + new_data) + '\n'
|
||||
|
||||
def test_save(self, lineparser):
|
||||
def test_save(self, tmpdir, lineparser):
|
||||
"""Test save()."""
|
||||
new_data = ['new data 1', 'new data 2']
|
||||
lineparser.new_data = new_data
|
||||
lineparser.save()
|
||||
assert lineparser._data == self._get_expected(new_data)
|
||||
assert (tmpdir / 'file').read() == self._get_expected(new_data)
|
||||
|
||||
def test_clear(self, tmpdir, lineparser):
|
||||
lineparser.new_data = ['one', 'two']
|
||||
lineparser.save()
|
||||
assert (tmpdir / 'file').read() == "old data 1\nold data 2\none\ntwo\n"
|
||||
|
||||
lineparser.new_data = ['one', 'two']
|
||||
lineparser.clear()
|
||||
lineparser.save()
|
||||
assert not lineparser.new_data
|
||||
assert (tmpdir / 'file').read() == ""
|
||||
|
||||
def test_iter_without_open(self, lineparser):
|
||||
"""Test __iter__ without having called open()."""
|
||||
@ -170,9 +130,10 @@ class TestAppendLineParser:
|
||||
with linep.open():
|
||||
assert list(linep) == new_data
|
||||
|
||||
def test_get_recent_none(self):
|
||||
def test_get_recent_none(self, tmpdir):
|
||||
"""Test get_recent with no data."""
|
||||
linep = AppendLineParserTestable('this really', 'does not matter')
|
||||
(tmpdir / 'file2').ensure()
|
||||
linep = lineparsermod.AppendLineParser(str(tmpdir), 'file2')
|
||||
assert linep.get_recent() == []
|
||||
|
||||
def test_get_recent_little(self, lineparser):
|
||||
|
Loading…
Reference in New Issue
Block a user