Prevent duplicates in history completion.

Two things here. One is to use `WebHistory._new_history` only as a to-save
queue, so we now add entries to `_old_urls` when they are first created and
can now no longer iterate of `_new_history` in `__iter__()`.

Second is to stop blindly tacking new history entries on the end of the
history completion model. It does involve iterating over the model to find the
existing entry but we only do that if we know the duplicate is there, which is
fast to check.

This also ads another point of mutation to the history completion model which
may prove problematic if it leads to more segfaults.
This commit is contained in:
Jimmy 2015-03-12 20:15:03 +13:00
parent 734268187c
commit 1efe18ecc6
2 changed files with 19 additions and 8 deletions

View File

@ -99,8 +99,7 @@ class WebHistory(QWebHistoryInterface):
return self._new_history[key] return self._new_history[key]
def __iter__(self): def __iter__(self):
return itertools.chain(self._old_urls.values(), return self._old_urls.values().__iter__()
iter(self._new_history))
def get_recent(self): def get_recent(self):
"""Get the most recent history entries.""" """Get the most recent history entries."""
@ -123,6 +122,7 @@ class WebHistory(QWebHistoryInterface):
if not config.get('general', 'private-browsing'): if not config.get('general', 'private-browsing'):
entry = HistoryEntry(time.time(), url_string) entry = HistoryEntry(time.time(), url_string)
self._new_history.append(entry) self._new_history.append(entry)
self._old_urls[url_string] = entry
self.item_added.emit(entry) self.item_added.emit(entry)
def historyContains(self, url_string): def historyContains(self, url_string):

View File

@ -19,7 +19,8 @@
"""CompletionModels for URLs.""" """CompletionModels for URLs."""
from PyQt5.QtCore import pyqtSlot from PyQt5.QtCore import pyqtSlot, Qt
from PyQt5.QtGui import QStandardItem
from qutebrowser.utils import objreg from qutebrowser.utils import objreg
from qutebrowser.completion.models import base from qutebrowser.completion.models import base
@ -40,22 +41,32 @@ class UrlCompletionModel(base.BaseCompletionModel):
self._history_cat = self.new_category("History") self._history_cat = self.new_category("History")
quickmarks = objreg.get('quickmark-manager').marks.items() quickmarks = objreg.get('quickmark-manager').marks.items()
history = objreg.get('web-history') self._history = objreg.get('web-history')
for qm_name, qm_url in quickmarks: for qm_name, qm_url in quickmarks:
self.new_item(self._quickmark_cat, qm_url, qm_name) self.new_item(self._quickmark_cat, qm_url, qm_name)
for entry in history: for entry in self._history:
atime = int(entry.atime) atime = int(entry.atime)
self.new_item(self._history_cat, entry.url, "", str(atime), self.new_item(self._history_cat, entry.url, "", str(atime),
sort=atime) sort=atime)
history.item_added.connect(self.on_history_item_added) self._history.item_added.connect(self.on_history_item_added)
@pyqtSlot(object) @pyqtSlot(object)
def on_history_item_added(self, item): def on_history_item_added(self, item):
"""Slot called when a new history item was added.""" """Slot called when a new history item was added."""
if item.url: if item.url:
atime = int(item.atime) atime = int(item.atime)
self.new_item(self._quickmark_cat, item.url, "", str(atime), if self._history.historyContains(item.url):
for i in range(self._history_cat.rowCount()):
name = self._history_cat.child(i, 0)
if not name:
continue
if name.text() == item.url:
self._history_cat.setChild(i, 2, QStandardItem(str(atime)))
name.setData(str(atime), base.Role.sort)
break
else:
self.new_item(self._history_cat, item.url, "", str(atime),
sort=atime) sort=atime)