Revert "Use SQL for quickmark/bookmark storage."

This reverts commit fa1ebb03b70dfff4ac64038e67d9bab04b984de5.
This commit is contained in:
Ryan Roden-Corrent 2017-02-28 08:43:11 -05:00
parent e3a33ca427
commit 80619c88b3
2 changed files with 81 additions and 41 deletions

View File

@ -1260,15 +1260,13 @@ class CommandDispatcher:
if name is None: if name is None:
url = self._current_url() url = self._current_url()
try: try:
quickmark_manager.delete_by_qurl(url) name = quickmark_manager.get_by_qurl(url)
except urlmarks.DoesNotExistError as e: except urlmarks.DoesNotExistError as e:
raise cmdexc.CommandError(str(e)) raise cmdexc.CommandError(str(e))
else:
try: try:
quickmark_manager.delete(name) quickmark_manager.delete(name)
except KeyError: except KeyError:
raise cmdexc.CommandError( raise cmdexc.CommandError("Quickmark '{}' not found!".format(name))
"Quickmark '{}' not found!".format(name))
@cmdutils.register(instance='command-dispatcher', scope='window') @cmdutils.register(instance='command-dispatcher', scope='window')
def bookmark_add(self, url=None, title=None, toggle=False): def bookmark_add(self, url=None, title=None, toggle=False):

View File

@ -29,13 +29,14 @@ import os
import html import html
import os.path import os.path
import functools import functools
import collections
from PyQt5.QtCore import QUrl from PyQt5.QtCore import pyqtSignal, QUrl, QObject
from qutebrowser.utils import (message, usertypes, qtutils, urlutils, from qutebrowser.utils import (message, usertypes, qtutils, urlutils,
standarddir, objreg, log) standarddir, objreg, log)
from qutebrowser.commands import cmdutils from qutebrowser.commands import cmdutils
from qutebrowser.misc import lineparser, sql from qutebrowser.misc import lineparser
class Error(Exception): class Error(Exception):
@ -66,18 +67,29 @@ class AlreadyExistsError(Error):
pass pass
class UrlMarkManager(sql.SqlTable): class UrlMarkManager(QObject):
"""Base class for BookmarkManager and QuickmarkManager. """Base class for BookmarkManager and QuickmarkManager.
Attributes: Attributes:
marks: An OrderedDict of all quickmarks/bookmarks. marks: An OrderedDict of all quickmarks/bookmarks.
_lineparser: The LineParser used for the marks _lineparser: The LineParser used for the marks
Signals:
changed: Emitted when anything changed.
added: Emitted when a new quickmark/bookmark was added.
removed: Emitted when an existing quickmark/bookmark was removed.
""" """
def __init__(self, name, fields, primary_key, parent=None): changed = pyqtSignal()
"""Initialize and read marks.""" added = pyqtSignal(str, str)
super().__init__(name, fields, primary_key, parent) removed = pyqtSignal(str)
def __init__(self, parent=None):
"""Initialize and read quickmarks."""
super().__init__(parent)
self.marks = collections.OrderedDict()
self._init_lineparser() self._init_lineparser()
for line in self._lineparser: for line in self._lineparser:
@ -98,17 +110,31 @@ class UrlMarkManager(sql.SqlTable):
def save(self): def save(self):
"""Save the marks to disk.""" """Save the marks to disk."""
self._lineparser.data = [' '.join(tpl) for tpl in self] self._lineparser.data = [' '.join(tpl) for tpl in self.marks.items()]
self._lineparser.save() self._lineparser.save()
def delete(self, key):
"""Delete a quickmark/bookmark.
Args:
key: The key to delete (name for quickmarks, URL for bookmarks.)
"""
del self.marks[key]
self.changed.emit()
self.removed.emit(key)
class QuickmarkManager(UrlMarkManager): class QuickmarkManager(UrlMarkManager):
"""Manager for quickmarks.""" """Manager for quickmarks.
def __init__(self, parent=None): The primary key for quickmarks is their *name*, this means:
super().__init__('Quickmarks', ['name', 'url'], primary_key='name',
parent=parent) - self.marks maps names to URLs.
- changed gets emitted with the name as first argument and the URL as
second argument.
- removed gets emitted with the name as argument.
"""
def _init_lineparser(self): def _init_lineparser(self):
self._lineparser = lineparser.LineParser( self._lineparser = lineparser.LineParser(
@ -125,7 +151,7 @@ class QuickmarkManager(UrlMarkManager):
except ValueError: except ValueError:
message.error("Invalid quickmark '{}'".format(line)) message.error("Invalid quickmark '{}'".format(line))
else: else:
self.insert([key, url]) self.marks[key] = url
def prompt_save(self, url): def prompt_save(self, url):
"""Prompt for a new quickmark name to be added and add it. """Prompt for a new quickmark name to be added and add it.
@ -165,32 +191,41 @@ class QuickmarkManager(UrlMarkManager):
def set_mark(): def set_mark():
"""Really set the quickmark.""" """Really set the quickmark."""
self.insert([name, url], replace=True) self.marks[name] = url
self.changed.emit()
self.added.emit(name, url)
log.misc.debug("Added quickmark {} for {}".format(name, url)) log.misc.debug("Added quickmark {} for {}".format(name, url))
if name in self: if name in self.marks:
message.confirm_async( message.confirm_async(
title="Override existing quickmark?", title="Override existing quickmark?",
yes_action=set_mark, default=True) yes_action=set_mark, default=True)
else: else:
set_mark() set_mark()
def delete_by_qurl(self, url): def get_by_qurl(self, url):
"""Delete a quickmark by QUrl (as opposed to by name).""" """Look up a quickmark by QUrl, returning its name.
Takes O(n) time, where n is the number of quickmarks.
Use a name instead where possible.
"""
qtutils.ensure_valid(url) qtutils.ensure_valid(url)
urlstr = url.toString(QUrl.RemovePassword | QUrl.FullyEncoded) urlstr = url.toString(QUrl.RemovePassword | QUrl.FullyEncoded)
try: try:
self.delete(urlstr, field='url') index = list(self.marks.values()).index(urlstr)
except KeyError: key = list(self.marks.keys())[index]
raise DoesNotExistError("Quickmark for '{}' not found!" except ValueError:
.format(urlstr)) raise DoesNotExistError(
"Quickmark for '{}' not found!".format(urlstr))
return key
def get(self, name): def get(self, name):
"""Get the URL of the quickmark named name as a QUrl.""" """Get the URL of the quickmark named name as a QUrl."""
if name not in self: if name not in self.marks:
raise DoesNotExistError("Quickmark '{}' does not exist!" raise DoesNotExistError(
.format(name)) "Quickmark '{}' does not exist!".format(name))
urlstr = self[name].url urlstr = self.marks[name]
try: try:
url = urlutils.fuzzy_url(urlstr, do_search=False) url = urlutils.fuzzy_url(urlstr, do_search=False)
except urlutils.InvalidUrlError as e: except urlutils.InvalidUrlError as e:
@ -201,11 +236,15 @@ class QuickmarkManager(UrlMarkManager):
class BookmarkManager(UrlMarkManager): class BookmarkManager(UrlMarkManager):
"""Manager for bookmarks.""" """Manager for bookmarks.
def __init__(self, parent=None): The primary key for bookmarks is their *url*, this means:
super().__init__('Bookmarks', ['url', 'title'], primary_key='url',
parent=parent) - self.marks maps URLs to titles.
- changed gets emitted with the URL as first argument and the title as
second argument.
- removed gets emitted with the URL as argument.
"""
def _init_lineparser(self): def _init_lineparser(self):
bookmarks_directory = os.path.join(standarddir.config(), 'bookmarks') bookmarks_directory = os.path.join(standarddir.config(), 'bookmarks')
@ -223,9 +262,10 @@ class BookmarkManager(UrlMarkManager):
def _parse_line(self, line): def _parse_line(self, line):
parts = line.split(maxsplit=1) parts = line.split(maxsplit=1)
urlstr = parts[0] if len(parts) == 2:
title = parts[1] if len(parts) == 2 else '' self.marks[parts[0]] = parts[1]
self.insert([urlstr, title]) elif len(parts) == 1:
self.marks[parts[0]] = ''
def add(self, url, title, *, toggle=False): def add(self, url, title, *, toggle=False):
"""Add a new bookmark. """Add a new bookmark.
@ -246,12 +286,14 @@ class BookmarkManager(UrlMarkManager):
urlstr = url.toString(QUrl.RemovePassword | QUrl.FullyEncoded) urlstr = url.toString(QUrl.RemovePassword | QUrl.FullyEncoded)
if urlstr in self: if urlstr in self.marks:
if toggle: if toggle:
self.delete(urlstr) del self.marks[urlstr]
return False return False
else: else:
raise AlreadyExistsError("Bookmark already exists!") raise AlreadyExistsError("Bookmark already exists!")
else: else:
self.insert([urlstr, title]) self.marks[urlstr] = title
self.changed.emit()
self.added.emit(title, urlstr)
return True return True