diff --git a/qutebrowser/app.py b/qutebrowser/app.py index bf8380921..f94d37ef0 100644 --- a/qutebrowser/app.py +++ b/qutebrowser/app.py @@ -151,7 +151,8 @@ class Application(QApplication): log.init.debug("Initializing websettings...") websettings.init() log.init.debug("Initializing quickmarks...") - quickmarks.init() + quickmark_manager = quickmarks.QuickmarkManager() + objreg.register('quickmark-manager', quickmark_manager) log.init.debug("Initializing proxy...") proxy.init() log.init.debug("Initializing cookies...") @@ -663,14 +664,19 @@ class Application(QApplication): pass else: to_save.append(("keyconfig", key_config.save)) - to_save += [("window geometry", self._save_geometry), - ("quickmarks", quickmarks.save)] + to_save += [("window geometry", self._save_geometry)] try: command_history = objreg.get('command-history') except KeyError: pass else: to_save.append(("command history", command_history.save)) + try: + quickmark_manager = objreg.get('quickmark-manager') + except KeyError: + pass + else: + to_save.append(("command history", quickmark_manager.save)) try: state_config = objreg.get('state-config') except KeyError: diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index 333195d6e..420580197 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -36,7 +36,7 @@ import pygments.formatters from qutebrowser.commands import userscripts, cmdexc, cmdutils from qutebrowser.config import config -from qutebrowser.browser import quickmarks, webelem +from qutebrowser.browser import webelem from qutebrowser.utils import (message, editor, usertypes, log, qtutils, urlutils, objreg, utils) @@ -815,7 +815,8 @@ class CommandDispatcher: @cmdutils.register(instance='command-dispatcher', scope='window') def quickmark_save(self): """Save the current page as a quickmark.""" - quickmarks.prompt_save(self._win_id, self._current_url()) + quickmark_manager = objreg.get('quickmark-manager') + quickmark_manager.prompt_save(self._win_id, self._current_url()) @cmdutils.register(instance='command-dispatcher', scope='window') def quickmark_load(self, name, tab=False, bg=False, window=False): @@ -827,7 +828,7 @@ class CommandDispatcher: bg: Load the quickmark in a new background tab. window: Load the quickmark in a new window. """ - url = quickmarks.get(name) + url = objreg.get('quickmark-manager').get(name) self._open(url, tab, bg, window) @cmdutils.register(instance='command-dispatcher', name='inspector', diff --git a/qutebrowser/browser/quickmarks.py b/qutebrowser/browser/quickmarks.py index e6b4f52a5..fb7249efb 100644 --- a/qutebrowser/browser/quickmarks.py +++ b/qutebrowser/browser/quickmarks.py @@ -27,91 +27,99 @@ to a file on shutdown, so it makes semse to keep them as strings here. import functools import collections -from PyQt5.QtCore import QStandardPaths, QUrl +from PyQt5.QtCore import pyqtSignal, QStandardPaths, QUrl, QObject from qutebrowser.utils import message, usertypes, urlutils, standarddir from qutebrowser.commands import cmdexc, cmdutils from qutebrowser.config import lineparser -marks = collections.OrderedDict() -linecp = None +class QuickmarkManager(QObject): + """Manager for quickmarks. -def init(): - """Read quickmarks from the config file.""" - global linecp - confdir = standarddir.get(QStandardPaths.ConfigLocation) - linecp = lineparser.LineConfigParser(confdir, 'quickmarks') - for line in linecp: - try: - key, url = line.rsplit(maxsplit=1) - except ValueError: - message.error(0, "Invalid quickmark '{}'".format(line)) + Attributes: + marks: An OrderedDict of all quickmarks. + _linecp: The LineConfigParser used for the quickmarks. + """ + + changed = pyqtSignal() + + def __init__(self, parent=None): + """Initialize and read quickmarks.""" + super().__init__(parent) + + self.marks = collections.OrderedDict() + + confdir = standarddir.get(QStandardPaths.ConfigLocation) + self._linecp = lineparser.LineConfigParser(confdir, 'quickmarks') + for line in self._linecp: + try: + key, url = line.rsplit(maxsplit=1) + except ValueError: + message.error(0, "Invalid quickmark '{}'".format(line)) + else: + self.marks[key] = url + + def save(self): + """Save the quickmarks to disk.""" + self._linecp.data = [' '.join(tpl) for tpl in self.marks.items()] + self._linecp.save() + + def prompt_save(self, win_id, url): + """Prompt for a new quickmark name to be added and add it. + + Args: + win_id: The current window ID. + url: The quickmark url as a QUrl. + """ + if not url.isValid(): + urlutils.invalid_url_error(win_id, url, "save quickmark") + return + urlstr = url.toString(QUrl.RemovePassword | QUrl.FullyEncoded) + message.ask_async( + win_id, "Add quickmark:", usertypes.PromptMode.text, + functools.partial(self.quickmark_add, win_id, urlstr)) + + @cmdutils.register(instance='quickmark-manager') + def quickmark_add(self, win_id: {'special': 'win_id'}, url, name): + """Add a new quickmark. + + Args: + win_id: The window ID to display the errors in. + url: The url to add as quickmark. + name: The name for the new quickmark. + """ + # We don't raise cmdexc.CommandError here as this can be called async + # via prompt_save. + if not name: + message.error(win_id, "Can't set mark with empty name!") + return + if not url: + message.error(win_id, "Can't set mark with empty URL!") + return + + def set_mark(): + """Really set the quickmark.""" + self.marks[name] = url + self.changed.emit() + + if name in self.marks: + message.confirm_async( + win_id, "Override existing quickmark?", set_mark, default=True) else: - marks[key] = url + set_mark() - -def save(): - """Save the quickmarks to disk.""" - linecp.data = [' '.join(tpl) for tpl in marks.items()] - linecp.save() - - -def prompt_save(win_id, url): - """Prompt for a new quickmark name to be added and add it. - - Args: - win_id: The current window ID. - url: The quickmark url as a QUrl. - """ - if not url.isValid(): - urlutils.invalid_url_error(win_id, url, "save quickmark") - return - urlstr = url.toString(QUrl.RemovePassword | QUrl.FullyEncoded) - message.ask_async(win_id, "Add quickmark:", usertypes.PromptMode.text, - functools.partial(quickmark_add, win_id, urlstr)) - - -@cmdutils.register() -def quickmark_add(win_id: {'special': 'win_id'}, url, name): - """Add a new quickmark. - - Args: - win_id: The window ID to display the errors in. - url: The url to add as quickmark. - name: The name for the new quickmark. - """ - # We don't raise cmdexc.CommandError here as this can be called async via - # prompt_save. - if not name: - message.error(win_id, "Can't set mark with empty name!") - return - if not url: - message.error(win_id, "Can't set mark with empty URL!") - return - - def set_mark(): - """Really set the quickmark.""" - marks[name] = url - - if name in marks: - message.confirm_async(win_id, "Override existing quickmark?", set_mark, - default=True) - else: - set_mark() - - -def get(name): - """Get the URL of the quickmark named name as a QUrl.""" - if name not in marks: - raise cmdexc.CommandError( - "Quickmark '{}' does not exist!".format(name)) - urlstr = marks[name] - try: - url = urlutils.fuzzy_url(urlstr) - except urlutils.FuzzyUrlError: - raise cmdexc.CommandError( - "Invalid URL for quickmark {}: {} ({})".format(name, urlstr, - url.errorString())) - return url + def get(self, name): + """Get the URL of the quickmark named name as a QUrl.""" + if name not in self.marks: + raise cmdexc.CommandError( + "Quickmark '{}' does not exist!".format(name)) + urlstr = self.marks[name] + try: + url = urlutils.fuzzy_url(urlstr) + except urlutils.FuzzyUrlError: + raise cmdexc.CommandError( + "Invalid URL for quickmark {}: {} ({})".format( + name, urlstr, url.errorString())) + return url