Merge bookmarks and quickmarks into urlmarks.

This commit is contained in:
Florian Bruhin 2015-07-26 16:37:10 +02:00
parent b52a41ac6f
commit 2f11b41ae6
5 changed files with 126 additions and 164 deletions

View File

@ -44,8 +44,7 @@ import qutebrowser.resources # pylint: disable=unused-import
from qutebrowser.completion.models import instances as completionmodels
from qutebrowser.commands import cmdutils, runners, cmdexc
from qutebrowser.config import style, config, websettings, configexc
from qutebrowser.browser import (bookmarks, quickmarks, cookies, cache,
adblock, history)
from qutebrowser.browser import urlmarks, cookies, cache, adblock, history
from qutebrowser.browser.network import qutescheme, proxy, networkmanager
from qutebrowser.mainwindow import mainwindow
from qutebrowser.misc import readline, ipc, savemanager, sessions, crashsignal
@ -414,10 +413,10 @@ def _init_modules(args, crash_handler):
host_blocker.read_hosts()
objreg.register('host-blocker', host_blocker)
log.init.debug("Initializing quickmarks...")
quickmark_manager = quickmarks.QuickmarkManager(qApp)
quickmark_manager = urlmarks.QuickmarkManager(qApp)
objreg.register('quickmark-manager', quickmark_manager)
log.init.debug("Initializing bookmarks...")
bookmark_manager = bookmarks.BookmarkManager(qApp)
bookmark_manager = urlmarks.BookmarkManager(qApp)
objreg.register('bookmark-manager', bookmark_manager)
log.init.debug("Initializing proxy...")
proxy.init()

View File

@ -1,124 +0,0 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2015 Antoni Boucher <bouanto@zoho.com>
#
# 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/>.
"""Manager for bookmarks.
Note we violate our general QUrl rule by storing url strings in the bookmarks
OrderedDict. This is because we read them from a file at start and write them
to a file on shutdown, so it makes sense to keep them as strings here.
"""
import os
import os.path
import collections
from PyQt5.QtCore import pyqtSignal, QUrl, QObject
from qutebrowser.utils import message, standarddir, objreg
from qutebrowser.misc import lineparser
class BookmarkManager(QObject):
"""Manager for bookmarks.
Attributes:
bookmarks: An OrderedDict of all bookmarks.
_lineparser: The LineParser used for the bookmarks, or None
(when qutebrowser is started with -c '').
Signals:
changed: Emitted when anything changed.
added: Emitted when a new bookmark was added.
arg 0: The title of the bookmark.
arg 1: The URL of the bookmark, as string.
removed: Emitted when an existing bookmark was removed.
arg 0: The title of the bookmark.
"""
changed = pyqtSignal()
added = pyqtSignal(str, str)
removed = pyqtSignal(str)
def __init__(self, parent=None):
"""Initialize and read bookmarks."""
super().__init__(parent)
self.bookmarks = collections.OrderedDict()
if standarddir.config() is None:
self._lineparser = None
else:
bookmarks_directory = os.path.join(standarddir.config(),
'bookmarks')
if not os.path.isdir(bookmarks_directory):
os.makedirs(bookmarks_directory)
self._lineparser = lineparser.LineParser(
standarddir.config(), 'bookmarks/urls', parent=self)
for line in self._lineparser:
if not line.strip():
# Ignore empty or whitespace-only lines.
continue
parts = line.split(maxsplit=1)
if len(parts) == 2:
self.bookmarks[parts[0]] = parts[1]
elif len(parts) == 1:
self.bookmarks[parts[0]] = ''
filename = os.path.join(standarddir.config(), 'bookmarks/urls')
objreg.get('save-manager').add_saveable(
'bookmark-manager', self.save, self.changed,
filename=filename)
def save(self):
"""Save the bookmarks to disk."""
if self._lineparser is not None:
self._lineparser.data = [' '.join(tpl)
for tpl in self.bookmarks.items()]
self._lineparser.save()
def add(self, win_id, url, title):
"""Add a new bookmark.
Args:
win_id: The window ID to display the errors in.
url: The url to add as bookmark.
title: The title for the new bookmark.
"""
urlstr = url.toString(QUrl.RemovePassword | QUrl.FullyEncoded)
if urlstr in self.bookmarks:
message.error(win_id, "Bookmark already exists!")
else:
self.bookmarks[urlstr] = title
self.changed.emit()
self.added.emit(title, urlstr)
message.info(win_id, "Bookmark added")
def delete(self, url):
"""Delete a bookmark.
Args:
url: The url of the bookmark to delete.
"""
del self.bookmarks[url]
self.changed.emit()
self.removed.emit(url)

View File

@ -1,6 +1,7 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2015 Antoni Boucher <bouanto@zoho.com>
#
# This file is part of qutebrowser.
#
@ -17,13 +18,14 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
"""Manager for quickmarks.
"""Managers for bookmarks and quickmarks.
Note we violate our general QUrl rule by storing url strings in the marks
OrderedDict. This is because we read them from a file at start and write them
to a file on shutdown, so it makes sense to keep them as strings here.
"""
import os
import os.path
import functools
import collections
@ -35,22 +37,19 @@ from qutebrowser.commands import cmdexc, cmdutils
from qutebrowser.misc import lineparser
class QuickmarkManager(QObject):
class UrlMarkManager(QObject):
"""Manager for quickmarks.
"""Base class for BookmarkManager and QuickmarkManager.
Attributes:
marks: An OrderedDict of all quickmarks.
_lineparser: The LineParser used for the quickmarks, or None
marks: An OrderedDict of all quickmarks/bookmarks.
_lineparser: The LineParser used for the marks, or None
(when qutebrowser is started with -c '').
Signals:
changed: Emitted when anything changed.
added: Emitted when a new quickmark was added.
arg 0: The name of the quickmark.
arg 1: The URL of the quickmark, as string.
removed: Emitted when an existing quickmark was removed.
arg 0: The name of the quickmark.
added: Emitted when a new quickmark/bookmark was added.
removed: Emitted when an existing quickmark/bookmark was removed.
"""
changed = pyqtSignal()
@ -62,35 +61,76 @@ class QuickmarkManager(QObject):
super().__init__(parent)
self.marks = collections.OrderedDict()
self._lineparser = None
if standarddir.config() is None:
self._lineparser = None
else:
self._lineparser = lineparser.LineParser(
standarddir.config(), 'quickmarks', parent=self)
for line in self._lineparser:
if not line.strip():
# Ignore empty or whitespace-only lines.
continue
try:
key, url = line.rsplit(maxsplit=1)
except ValueError:
message.error('current', "Invalid quickmark '{}'".format(
line))
else:
self.marks[key] = url
filename = os.path.join(standarddir.config(), 'quickmarks')
objreg.get('save-manager').add_saveable(
'quickmark-manager', self.save, self.changed,
filename=filename)
return
self._init_lineparser()
for line in self._lineparser:
if not line.strip():
# Ignore empty or whitespace-only lines.
continue
self._parse_line(line)
self._init_savemanager(objreg.get('save-manager'))
def _init_lineparser(self):
raise NotImplementedError
def _parse_line(self, line):
raise NotImplementedError
def _init_savemanager(self, _save_manager):
raise NotImplementedError
def save(self):
"""Save the quickmarks to disk."""
"""Save the marks to disk."""
if self._lineparser is not None:
self._lineparser.data = [' '.join(tpl)
for tpl in self.marks.items()]
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):
"""Manager for quickmarks.
The primary key for quickmarks is their *name*, this means:
- 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):
self._lineparser = lineparser.LineParser(
standarddir.config(), 'quickmarks', parent=self)
def _init_savemanager(self, save_manager):
filename = os.path.join(standarddir.config(), 'quickmarks')
save_manager.add_saveable('quickmark-manager', self.save, self.changed,
filename=filename)
def _parse_line(self, line):
try:
key, url = line.rsplit(maxsplit=1)
except ValueError:
message.error('current', "Invalid quickmark '{}'".format(
line))
else:
self.marks[key] = url
def prompt_save(self, win_id, url):
"""Prompt for a new quickmark name to be added and add it.
@ -145,12 +185,9 @@ class QuickmarkManager(QObject):
name: The name of the quickmark to delete.
"""
try:
del self.marks[name]
self.delete(name)
except KeyError:
raise cmdexc.CommandError("Quickmark '{}' not found!".format(name))
else:
self.changed.emit()
self.removed.emit(name)
def get(self, name):
"""Get the URL of the quickmark named name as a QUrl."""
@ -168,3 +205,53 @@ class QuickmarkManager(QObject):
raise cmdexc.CommandError("Invalid URL for quickmark {}: "
"{}{}".format(name, urlstr, errstr))
return url
class BookmarkManager(UrlMarkManager):
"""Manager for bookmarks.
The primary key for bookmarks is their *url*, this means:
- 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):
bookmarks_directory = os.path.join(standarddir.config(), 'bookmarks')
if not os.path.isdir(bookmarks_directory):
os.makedirs(bookmarks_directory)
self._lineparser = lineparser.LineParser(
standarddir.config(), 'bookmarks/urls', parent=self)
def _init_savemanager(self, save_manager):
filename = os.path.join(standarddir.config(), 'bookmarks/urls')
save_manager.add_saveable('bookmark-manager', self.save, self.changed,
filename=filename)
def _parse_line(self, line):
parts = line.split(maxsplit=1)
if len(parts) == 2:
self.marks[parts[0]] = parts[1]
elif len(parts) == 1:
self.marks[parts[0]] = ''
def add(self, win_id, url, title):
"""Add a new bookmark.
Args:
win_id: The window ID to display the errors in.
url: The url to add as bookmark.
title: The title for the new bookmark.
"""
urlstr = url.toString(QUrl.RemovePassword | QUrl.FullyEncoded)
if urlstr in self.marks:
message.error(win_id, "Bookmark already exists!")
else:
self.marks[urlstr] = title
self.changed.emit()
self.added.emit(title, urlstr)
message.info(win_id, "Bookmark added")

View File

@ -124,7 +124,7 @@ class BookmarkCompletionModel(base.BaseCompletionModel):
super().__init__(parent)
self.columns_to_highlight.append(0)
cat = self.new_category("Bookmarks")
bookmarks = objreg.get('bookmark-manager').bookmarks.items()
bookmarks = objreg.get('bookmark-manager').marks.items()
if match_field == 'url':
for bm_url, bm_title in bookmarks:
self.new_item(cat, bm_url, bm_title)

View File

@ -54,7 +54,7 @@ class UrlCompletionModel(base.BaseCompletionModel):
quickmark_manager.removed.connect(self.on_quickmark_removed)
bookmark_manager = objreg.get('bookmark-manager')
bookmarks = bookmark_manager.bookmarks.items()
bookmarks = bookmark_manager.marks.items()
for bm_url, bm_title in bookmarks:
self._add_bookmark_entry(bm_title, bm_url)
bookmark_manager.added.connect(self.on_bookmark_added)