Do history loading after qutebrowser has started.

This commit is contained in:
Florian Bruhin 2015-06-02 23:34:55 +02:00
parent b43d8b13d8
commit a545b919f7
4 changed files with 74 additions and 15 deletions

View File

@ -50,7 +50,7 @@ from qutebrowser.mainwindow import mainwindow
from qutebrowser.misc import readline, ipc, savemanager, sessions, crashsignal from qutebrowser.misc import readline, ipc, savemanager, sessions, crashsignal
from qutebrowser.misc import utilcmds # pylint: disable=unused-import from qutebrowser.misc import utilcmds # pylint: disable=unused-import
from qutebrowser.utils import (log, version, message, utils, qtutils, urlutils, from qutebrowser.utils import (log, version, message, utils, qtutils, urlutils,
objreg, usertypes, standarddir, error) objreg, usertypes, standarddir, error, debug)
# We import utilcmds to run the cmdutils.register decorators. # We import utilcmds to run the cmdutils.register decorators.
@ -148,7 +148,9 @@ def init(args, crash_handler):
error.handle_fatal_exc(e, args, "Error while initializing!", error.handle_fatal_exc(e, args, "Error while initializing!",
pre_text="Error while initializing") pre_text="Error while initializing")
sys.exit(usertypes.Exit.err_init) sys.exit(usertypes.Exit.err_init)
QTimer.singleShot(0, functools.partial(_process_args, args)) QTimer.singleShot(0, functools.partial(_process_args, args))
QTimer.singleShot(10, functools.partial(_init_late_modules, args))
log.init.debug("Initializing eventfilter...") log.init.debug("Initializing eventfilter...")
event_filter = EventFilter(qApp) event_filter = EventFilter(qApp)
@ -428,6 +430,23 @@ def _init_modules(args, crash_handler):
objreg.get('config').changed.connect(_maybe_hide_mouse_cursor) objreg.get('config').changed.connect(_maybe_hide_mouse_cursor)
def _init_late_modules(args):
"""Initialize modules which can be inited after the window is shown."""
try:
log.init.debug("Reading web history...")
reader = objreg.get('web-history').async_read()
with debug.log_time(log.init, 'Reading history'):
while True:
QApplication.processEvents()
next(reader)
except StopIteration:
pass
except (OSError, UnicodeDecodeError) as e:
error.handle_fatal_exc(e, args, "Error while initializing!",
pre_text="Error while initializing")
sys.exit(usertypes.Exit.err_init)
class Quitter: class Quitter:
"""Utility class to quit/restart the QApplication. """Utility class to quit/restart the QApplication.

View File

@ -67,23 +67,30 @@ class WebHistory(QWebHistoryInterface):
_history_dict: An OrderedDict of URLs read from the on-disk history. _history_dict: An OrderedDict of URLs read from the on-disk history.
_new_history: A list of HistoryEntry items of the current session. _new_history: A list of HistoryEntry items of the current session.
_saved_count: How many HistoryEntries have been written to disk. _saved_count: How many HistoryEntries have been written to disk.
_initial_read_started: Whether async_read was called.
_initial_read_done: Whether async_read has completed.
_temp_history: OrderedDict of temporary history entries before
async_read was called.
Signals: Signals:
item_about_to_be_added: Emitted before a new HistoryEntry is added. add_completion_item: Emitted before a new HistoryEntry is added.
arg: The new HistoryEntry. arg: The new HistoryEntry.
item_added: Emitted after a new HistoryEntry is added. item_added: Emitted after a new HistoryEntry is added.
arg: The new HistoryEntry. arg: The new HistoryEntry.
""" """
item_about_to_be_added = pyqtSignal(HistoryEntry) add_completion_item = pyqtSignal(HistoryEntry)
item_added = pyqtSignal(HistoryEntry) item_added = pyqtSignal(HistoryEntry)
async_read_done = pyqtSignal()
def __init__(self, parent=None): def __init__(self, parent=None):
super().__init__(parent) super().__init__(parent)
self._initial_read_started = False
self._initial_read_done = False
self._lineparser = lineparser.AppendLineParser( self._lineparser = lineparser.AppendLineParser(
standarddir.data(), 'history', parent=self) standarddir.data(), 'history', parent=self)
self._history_dict = collections.OrderedDict() self._history_dict = collections.OrderedDict()
self._read_history() self._temp_history = collections.OrderedDict()
self._new_history = [] self._new_history = []
self._saved_count = 0 self._saved_count = 0
objreg.get('save-manager').add_saveable( objreg.get('save-manager').add_saveable(
@ -101,12 +108,21 @@ class WebHistory(QWebHistoryInterface):
def __len__(self): def __len__(self):
return len(self._history_dict) return len(self._history_dict)
def _read_history(self): def async_read(self):
"""Read the initial history.""" """Read the initial history."""
if standarddir.data() is None: if self._initial_read_started:
log.init.debug("Ignoring async_read() because reading is started.")
return return
self._initial_read_started = True
if standarddir.data() is None:
self._initial_read_done = True
self.async_read_done.emit()
return
with self._lineparser.open(): with self._lineparser.open():
for line in self._lineparser: for line in self._lineparser:
yield
data = line.rstrip().split(maxsplit=1) data = line.rstrip().split(maxsplit=1)
if not data: if not data:
# empty line # empty line
@ -128,8 +144,24 @@ class WebHistory(QWebHistoryInterface):
# information about previous hits change the items in # information about previous hits change the items in
# old_urls to be lists or change HistoryEntry to have a # old_urls to be lists or change HistoryEntry to have a
# list of atimes. # list of atimes.
self._history_dict[url] = HistoryEntry(atime, url) entry = HistoryEntry(atime, url)
self._history_dict.move_to_end(url) self._add_entry(entry)
self._initial_read_done = True
self.async_read_done.emit()
for url, entry in self._temp_history.items():
entry = HistoryEntry(atime, url)
self._new_history.append(entry)
self._add_entry(entry)
self.add_completion_item.emit(entry)
def _add_entry(self, entry, target=None):
"""Add an entry to self._history_dict or another given OrderedDict."""
if target is None:
target = self._history_dict
target[entry.url_string] = entry
target.move_to_end(entry.url_string)
def get_recent(self): def get_recent(self):
"""Get the most recent history entries.""" """Get the most recent history entries."""
@ -151,13 +183,16 @@ class WebHistory(QWebHistoryInterface):
""" """
if not url_string: if not url_string:
return return
if not config.get('general', 'private-browsing'): if config.get('general', 'private-browsing'):
return
entry = HistoryEntry(time.time(), url_string) entry = HistoryEntry(time.time(), url_string)
self.item_about_to_be_added.emit(entry) if self._initial_read_done:
self.add_completion_item.emit(entry)
self._new_history.append(entry) self._new_history.append(entry)
self._history_dict[url_string] = entry self._add_entry(entry)
self._history_dict.move_to_end(url_string)
self.item_added.emit(entry) self.item_added.emit(entry)
else:
self._add_entry(entry, target=self._temp_history)
def historyContains(self, url_string): def historyContains(self, url_string):
"""Called by WebKit to determine if an URL is contained in the history. """Called by WebKit to determine if an URL is contained in the history.

View File

@ -165,6 +165,11 @@ def init():
quickmark_manager.changed.connect( quickmark_manager.changed.connect(
functools.partial(update, [usertypes.Completion.quickmark_by_url, functools.partial(update, [usertypes.Completion.quickmark_by_url,
usertypes.Completion.quickmark_by_name])) usertypes.Completion.quickmark_by_name]))
session_manager = objreg.get('session-manager') session_manager = objreg.get('session-manager')
session_manager.update_completion.connect( session_manager.update_completion.connect(
functools.partial(update, [usertypes.Completion.sessions])) functools.partial(update, [usertypes.Completion.sessions]))
history = objreg.get('web-history')
history.async_read_done.connect(
functools.partial(update, [usertypes.Completion.url]))

View File

@ -54,7 +54,7 @@ class UrlCompletionModel(base.BaseCompletionModel):
history = utils.newest_slice(self._history, max_history) history = utils.newest_slice(self._history, max_history)
for entry in history: for entry in history:
self._add_history_entry(entry) self._add_history_entry(entry)
self._history.item_about_to_be_added.connect( self._history.add_completion_item.connect(
self.on_history_item_added) self.on_history_item_added)
objreg.get('config').changed.connect(self.reformat_timestamps) objreg.get('config').changed.connect(self.reformat_timestamps)