Initialize completions lazily and only once.
Before, we initialized the completions once for every window spawned, which was a waste of CPU-time and RAM. Now we only initialize them once, when the user uses the completion for the first time.
This commit is contained in:
parent
389feab1df
commit
74892ac8e4
@ -38,6 +38,7 @@ from PyQt5.QtCore import (pyqtSlot, qInstallMessageHandler, QTimer, QUrl,
|
||||
|
||||
import qutebrowser
|
||||
import qutebrowser.resources # pylint: disable=unused-import
|
||||
from qutebrowser.completion.models import instances as completionmodels
|
||||
from qutebrowser.commands import cmdutils, runners
|
||||
from qutebrowser.config import style, config, websettings, configexc
|
||||
from qutebrowser.browser import quickmarks, cookies, cache, adblock, history
|
||||
@ -163,6 +164,7 @@ class Application(QApplication):
|
||||
|
||||
def _init_modules(self):
|
||||
"""Initialize all 'modules' which need to be initialized."""
|
||||
# pylint: disable=too-many-statements
|
||||
log.init.debug("Initializing save manager...")
|
||||
save_manager = savemanager.SaveManager(self)
|
||||
objreg.register('save-manager', save_manager)
|
||||
@ -205,6 +207,8 @@ class Application(QApplication):
|
||||
log.init.debug("Initializing cache...")
|
||||
diskcache = cache.DiskCache(self)
|
||||
objreg.register('cache', diskcache)
|
||||
log.init.debug("Initializing completions...")
|
||||
completionmodels.init()
|
||||
if not session_manager.exists(self._args.session):
|
||||
log.init.debug("Initializing main window...")
|
||||
window = mainwindow.MainWindow()
|
||||
|
@ -19,14 +19,12 @@
|
||||
|
||||
"""Completer attached to a CompletionView."""
|
||||
|
||||
from PyQt5.QtCore import pyqtSlot, QObject, QTimer, Qt
|
||||
from PyQt5.QtCore import pyqtSlot, QObject, QTimer
|
||||
|
||||
from qutebrowser.config import config, configdata
|
||||
from qutebrowser.config import config
|
||||
from qutebrowser.commands import cmdutils, runners
|
||||
from qutebrowser.utils import usertypes, log, objreg, utils
|
||||
from qutebrowser.completion.models import miscmodels, urlmodel, configmodel
|
||||
from qutebrowser.completion.models.sortfilter import (
|
||||
CompletionFilterModel as CFM)
|
||||
from qutebrowser.completion.models import instances
|
||||
|
||||
|
||||
class Completer(QObject):
|
||||
@ -34,7 +32,6 @@ class Completer(QObject):
|
||||
"""Completer which manages completions in a CompletionView.
|
||||
|
||||
Attributes:
|
||||
models: dict of available completion models.
|
||||
_cmd: The statusbar Command object this completer belongs to.
|
||||
_ignore_change: Whether to ignore the next completion update.
|
||||
_win_id: The window ID this completer is in.
|
||||
@ -53,15 +50,6 @@ class Completer(QObject):
|
||||
self._cmd.textEdited.connect(self.on_text_edited)
|
||||
self._ignore_change = False
|
||||
self._empty_item_idx = None
|
||||
|
||||
self._models = {
|
||||
usertypes.Completion.option: {},
|
||||
usertypes.Completion.value: {},
|
||||
}
|
||||
self._init_static_completions()
|
||||
self._init_setting_completions()
|
||||
self.init_quickmark_completions()
|
||||
self.init_session_completion()
|
||||
self._timer = QTimer()
|
||||
self._timer.setSingleShot(True)
|
||||
self._timer.setInterval(0)
|
||||
@ -79,56 +67,6 @@ class Completer(QObject):
|
||||
window=self._win_id)
|
||||
return completion.model()
|
||||
|
||||
def _init_static_completions(self):
|
||||
"""Initialize the static completion models."""
|
||||
self._models[usertypes.Completion.command] = CFM(
|
||||
miscmodels.CommandCompletionModel(self), self)
|
||||
self._models[usertypes.Completion.helptopic] = CFM(
|
||||
miscmodels.HelpCompletionModel(self), self)
|
||||
self._models[usertypes.Completion.url] = CFM(
|
||||
urlmodel.UrlCompletionModel(self), self,
|
||||
dumb_sort=Qt.DescendingOrder)
|
||||
|
||||
def _init_setting_completions(self):
|
||||
"""Initialize setting completion models."""
|
||||
self._models[usertypes.Completion.section] = CFM(
|
||||
configmodel.SettingSectionCompletionModel(self), self)
|
||||
self._models[usertypes.Completion.option] = {}
|
||||
self._models[usertypes.Completion.value] = {}
|
||||
for sectname in configdata.DATA:
|
||||
model = configmodel.SettingOptionCompletionModel(sectname, self)
|
||||
self._models[usertypes.Completion.option][sectname] = CFM(
|
||||
model, self)
|
||||
self._models[usertypes.Completion.value][sectname] = {}
|
||||
for opt in configdata.DATA[sectname].keys():
|
||||
model = configmodel.SettingValueCompletionModel(sectname, opt,
|
||||
self)
|
||||
self._models[usertypes.Completion.value][sectname][opt] = CFM(
|
||||
model, self)
|
||||
|
||||
@pyqtSlot()
|
||||
def init_quickmark_completions(self):
|
||||
"""Initialize quickmark completion models."""
|
||||
try:
|
||||
self._models[usertypes.Completion.quickmark_by_url].deleteLater()
|
||||
self._models[usertypes.Completion.quickmark_by_name].deleteLater()
|
||||
except KeyError:
|
||||
pass
|
||||
self._models[usertypes.Completion.quickmark_by_url] = CFM(
|
||||
miscmodels.QuickmarkCompletionModel('url', self), self)
|
||||
self._models[usertypes.Completion.quickmark_by_name] = CFM(
|
||||
miscmodels.QuickmarkCompletionModel('name', self), self)
|
||||
|
||||
@pyqtSlot()
|
||||
def init_session_completion(self):
|
||||
"""Initialize session completion model."""
|
||||
try:
|
||||
self._models[usertypes.Completion.sessions].deleteLater()
|
||||
except KeyError:
|
||||
pass
|
||||
self._models[usertypes.Completion.sessions] = CFM(
|
||||
miscmodels.SessionCompletionModel(self), self)
|
||||
|
||||
def _get_completion_model(self, completion, parts, cursor_part):
|
||||
"""Get a completion model based on an enum member.
|
||||
|
||||
@ -142,17 +80,17 @@ class Completer(QObject):
|
||||
"""
|
||||
if completion == usertypes.Completion.option:
|
||||
section = parts[cursor_part - 1]
|
||||
model = self._models[completion].get(section)
|
||||
model = instances.get(completion).get(section)
|
||||
elif completion == usertypes.Completion.value:
|
||||
section = parts[cursor_part - 2]
|
||||
option = parts[cursor_part - 1]
|
||||
try:
|
||||
model = self._models[completion][section][option]
|
||||
model = instances.get(completion)[section][option]
|
||||
except KeyError:
|
||||
# No completion model for this section/option.
|
||||
model = None
|
||||
else:
|
||||
model = self._models.get(completion)
|
||||
model = instances.get(completion)
|
||||
return model
|
||||
|
||||
def _filter_cmdline_parts(self, parts, cursor_part):
|
||||
@ -202,7 +140,7 @@ class Completer(QObject):
|
||||
"{}".format(parts, cursor_part))
|
||||
if cursor_part == 0:
|
||||
# '|' or 'set|'
|
||||
return self._models[usertypes.Completion.command]
|
||||
return instances.get(usertypes.Completion.command)
|
||||
# delegate completion to command
|
||||
try:
|
||||
completions = cmdutils.cmd_dict[parts[0]].completion
|
||||
|
154
qutebrowser/completion/models/instances.py
Normal file
154
qutebrowser/completion/models/instances.py
Normal file
@ -0,0 +1,154 @@
|
||||
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
|
||||
|
||||
# Copyright 2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
|
||||
#
|
||||
# This file is part of qutebrowser.
|
||||
#
|
||||
# qutebrowser is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# qutebrowser is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""Global instances of the completion models.
|
||||
|
||||
Module attributes:
|
||||
_instances: An dict of available completions.
|
||||
INITIALIZERS: A {usertypes.Completion: callable} dict of functions to
|
||||
initialize completions.
|
||||
"""
|
||||
|
||||
import functools
|
||||
|
||||
from PyQt5.QtCore import pyqtSlot, Qt
|
||||
|
||||
from qutebrowser.completion.models import miscmodels, urlmodel, configmodel
|
||||
from qutebrowser.completion.models.sortfilter import (
|
||||
CompletionFilterModel as CFM)
|
||||
from qutebrowser.utils import objreg, usertypes, log
|
||||
from qutebrowser.config import configdata
|
||||
|
||||
|
||||
_instances = {}
|
||||
|
||||
|
||||
def _init_command_completion():
|
||||
"""Initialize the command completion model."""
|
||||
log.completion.debug("Initializing command completion.")
|
||||
_instances[usertypes.Completion.command] = CFM(
|
||||
miscmodels.CommandCompletionModel())
|
||||
|
||||
|
||||
def _init_helptopic_completion():
|
||||
"""Initialize the helptopic completion model."""
|
||||
log.completion.debug("Initializing helptopic completion.")
|
||||
_instances[usertypes.Completion.helptopic] = CFM(
|
||||
miscmodels.HelpCompletionModel())
|
||||
|
||||
|
||||
def _init_url_completion():
|
||||
"""Initialize the URL completion model."""
|
||||
log.completion.debug("Initializing URL completion.")
|
||||
_instances[usertypes.Completion.url] = CFM(
|
||||
urlmodel.UrlCompletionModel(), dumb_sort=Qt.DescendingOrder)
|
||||
|
||||
|
||||
def _init_setting_completions():
|
||||
"""Initialize setting completion models."""
|
||||
log.completion.debug("Initializing setting completion.")
|
||||
_instances[usertypes.Completion.section] = CFM(
|
||||
configmodel.SettingSectionCompletionModel())
|
||||
_instances[usertypes.Completion.option] = {}
|
||||
_instances[usertypes.Completion.value] = {}
|
||||
for sectname in configdata.DATA:
|
||||
model = configmodel.SettingOptionCompletionModel(sectname)
|
||||
_instances[usertypes.Completion.option][sectname] = CFM(model)
|
||||
_instances[usertypes.Completion.value][sectname] = {}
|
||||
for opt in configdata.DATA[sectname].keys():
|
||||
model = configmodel.SettingValueCompletionModel(sectname, opt)
|
||||
_instances[usertypes.Completion.value][sectname][opt] = CFM(model)
|
||||
|
||||
|
||||
@pyqtSlot()
|
||||
def init_quickmark_completions():
|
||||
"""Initialize quickmark completion models."""
|
||||
log.completion.debug("Initializing quickmark completion.")
|
||||
try:
|
||||
_instances[usertypes.Completion.quickmark_by_url].deleteLater()
|
||||
_instances[usertypes.Completion.quickmark_by_name].deleteLater()
|
||||
except KeyError:
|
||||
pass
|
||||
_instances[usertypes.Completion.quickmark_by_url] = CFM(
|
||||
miscmodels.QuickmarkCompletionModel('url'))
|
||||
_instances[usertypes.Completion.quickmark_by_name] = CFM(
|
||||
miscmodels.QuickmarkCompletionModel('name'))
|
||||
|
||||
|
||||
@pyqtSlot()
|
||||
def init_session_completion():
|
||||
"""Initialize session completion model."""
|
||||
log.completion.debug("Initializing session completion.")
|
||||
try:
|
||||
_instances[usertypes.Completion.sessions].deleteLater()
|
||||
except KeyError:
|
||||
pass
|
||||
_instances[usertypes.Completion.sessions] = CFM(
|
||||
miscmodels.SessionCompletionModel())
|
||||
|
||||
|
||||
INITIALIZERS = {
|
||||
usertypes.Completion.command: _init_command_completion,
|
||||
usertypes.Completion.helptopic: _init_helptopic_completion,
|
||||
usertypes.Completion.url: _init_url_completion,
|
||||
usertypes.Completion.section: _init_setting_completions,
|
||||
usertypes.Completion.option: _init_setting_completions,
|
||||
usertypes.Completion.value: _init_setting_completions,
|
||||
usertypes.Completion.quickmark_by_url: init_quickmark_completions,
|
||||
usertypes.Completion.quickmark_by_name: init_quickmark_completions,
|
||||
usertypes.Completion.sessions: init_session_completion,
|
||||
}
|
||||
|
||||
|
||||
def get(completion):
|
||||
"""Get a certain completion. Initializes the completion if needed."""
|
||||
try:
|
||||
return _instances[completion]
|
||||
except KeyError:
|
||||
if completion in INITIALIZERS:
|
||||
INITIALIZERS[completion]()
|
||||
return _instances[completion]
|
||||
else:
|
||||
raise
|
||||
|
||||
|
||||
def update(completions):
|
||||
"""Update an already existing completion.
|
||||
|
||||
Args:
|
||||
completions: An iterable of usertypes.Completions.
|
||||
"""
|
||||
did_run = []
|
||||
for completion in completions:
|
||||
if completion in _instances:
|
||||
func = INITIALIZERS[completion]
|
||||
if func not in did_run:
|
||||
func()
|
||||
did_run.append(func)
|
||||
|
||||
|
||||
def init():
|
||||
"""Initialize completions. Note this only connects signals."""
|
||||
quickmark_manager = objreg.get('quickmark-manager')
|
||||
quickmark_manager.changed.connect(
|
||||
functools.partial(update, [usertypes.Completion.quickmark_by_url,
|
||||
usertypes.Completion.quickmark_by_name]))
|
||||
session_manager = objreg.get('session-manager')
|
||||
session_manager.update_completion.connect(
|
||||
functools.partial(update, [usertypes.Completion.sessions]))
|
@ -191,7 +191,6 @@ class MainWindow(QWidget):
|
||||
completion_obj = self._get_object('completion')
|
||||
tabs = self._get_object('tabbed-browser')
|
||||
cmd = self._get_object('status-command')
|
||||
completer = self._get_object('completer')
|
||||
search_runner = self._get_object('search-runner')
|
||||
message_bridge = self._get_object('message-bridge')
|
||||
mode_manager = self._get_object('mode-manager')
|
||||
@ -258,15 +257,6 @@ class MainWindow(QWidget):
|
||||
completion_obj.on_clear_completion_selection)
|
||||
cmd.hide_completion.connect(completion_obj.hide)
|
||||
|
||||
# quickmark completion
|
||||
quickmark_manager = objreg.get('quickmark-manager')
|
||||
quickmark_manager.changed.connect(completer.init_quickmark_completions)
|
||||
|
||||
# sessions completion
|
||||
session_manager = objreg.get('session-manager')
|
||||
session_manager.update_completion.connect(
|
||||
completer.init_session_completion)
|
||||
|
||||
@pyqtSlot()
|
||||
def resize_completion(self):
|
||||
"""Adjust completion according to config."""
|
||||
|
Loading…
Reference in New Issue
Block a user