Use SQL completion for the open command.

Now that history, bookmark, and quickmark storage are SQL-backed, use
a sql completion model to serve url completions.
This commit is contained in:
Ryan Roden-Corrent 2017-02-05 19:34:14 -05:00
parent 6e1ea89ca1
commit acea0d3c67
2 changed files with 12 additions and 173 deletions

View File

@ -19,180 +19,19 @@
"""Function to return the url completion model for the `open` command.""" """Function to return the url completion model for the `open` command."""
import datetime from qutebrowser.completion.models import sqlmodel
from PyQt5.QtCore import pyqtSlot, Qt
from qutebrowser.utils import objreg, utils, qtutils, log
from qutebrowser.completion.models import base
from qutebrowser.config import config
_URL_COLUMN = 0
_TEXT_COLUMN = 1
_TIME_COLUMN = 2
_model = None
_history_cat = None
_quickmark_cat = None
_bookmark_cat = None
def _delete_url(completion):
index = completion.currentIndex()
qtutils.ensure_valid(index)
category = index.parent()
index = category.child(index.row(), _URL_COLUMN)
qtutils.ensure_valid(category)
if category.data() == 'Bookmarks':
bookmark_manager = objreg.get('bookmark-manager')
bookmark_manager.delete(index.data())
elif category.data() == 'Quickmarks':
quickmark_manager = objreg.get('quickmark-manager')
sibling = index.sibling(index.row(), _TEXT_COLUMN)
qtutils.ensure_valid(sibling)
name = sibling.data()
quickmark_manager.delete(name)
def _remove_oldest_history():
"""Remove the oldest history entry."""
_history_cat.removeRow(0)
def _add_history_entry(entry):
"""Add a new history entry to the completion."""
_model.new_item(_history_cat, entry.url.toDisplayString(),
entry.title, _fmt_atime(entry.atime),
sort=int(entry.atime), userdata=entry.url)
max_history = config.get('completion', 'web-history-max-items')
if max_history != -1 and _history_cat.rowCount() > max_history:
_remove_oldest_history()
@config.change_filter('completion', 'timestamp-format')
def _reformat_timestamps():
"""Reformat the timestamps if the config option was changed."""
for i in range(_history_cat.rowCount()):
url_item = _history_cat.child(i, _URL_COLUMN)
atime_item = _history_cat.child(i, _TIME_COLUMN)
atime = url_item.data(base.Role.sort)
atime_item.setText(_fmt_atime(atime))
@pyqtSlot(object)
def _on_history_item_added(entry):
"""Slot called when a new history item was added."""
for i in range(_history_cat.rowCount()):
url_item = _history_cat.child(i, _URL_COLUMN)
atime_item = _history_cat.child(i, _TIME_COLUMN)
title_item = _history_cat.child(i, _TEXT_COLUMN)
if url_item.data(base.Role.userdata) == entry.url:
atime_item.setText(_fmt_atime(entry.atime))
title_item.setText(entry.title)
url_item.setData(int(entry.atime), base.Role.sort)
break
else:
_add_history_entry(entry)
@pyqtSlot()
def _on_history_cleared():
_history_cat.removeRows(0, _history_cat.rowCount())
def _remove_item(data, category, column):
"""Helper function for on_quickmark_removed and on_bookmark_removed.
Args:
data: The item to search for.
category: The category to search in.
column: The column to use for matching.
"""
for i in range(category.rowCount()):
item = category.child(i, column)
if item.data(Qt.DisplayRole) == data:
category.removeRow(i)
break
@pyqtSlot(str)
def _on_quickmark_removed(name):
"""Called when a quickmark has been removed by the user.
Args:
name: The name of the quickmark which has been removed.
"""
_remove_item(name, _quickmark_cat, _TEXT_COLUMN)
@pyqtSlot(str)
def _on_bookmark_removed(urltext):
"""Called when a bookmark has been removed by the user.
Args:
urltext: The url of the bookmark which has been removed.
"""
_remove_item(urltext, _bookmark_cat, _URL_COLUMN)
def _fmt_atime(atime):
"""Format an atime to a human-readable string."""
fmt = config.get('completion', 'timestamp-format')
if fmt is None:
return ''
try:
dt = datetime.datetime.fromtimestamp(atime)
except (ValueError, OSError, OverflowError):
# Different errors which can occur for too large values...
log.misc.error("Got invalid timestamp {}!".format(atime))
return '(invalid)'
else:
return dt.strftime(fmt)
def _init():
global _model, _quickmark_cat, _bookmark_cat, _history_cat
_model = base.CompletionModel(column_widths=(40, 50, 10),
dumb_sort=Qt.DescendingOrder,
delete_cur_item=_delete_url,
columns_to_filter=[_URL_COLUMN,
_TEXT_COLUMN])
_quickmark_cat = _model.new_category("Quickmarks")
_bookmark_cat = _model.new_category("Bookmarks")
_history_cat = _model.new_category("History")
quickmark_manager = objreg.get('quickmark-manager')
quickmarks = quickmark_manager.marks.items()
for qm_name, qm_url in quickmarks:
_model.new_item(_quickmark_cat, qm_url, qm_name)
quickmark_manager.added.connect(
lambda name, url: _model.new_item(_quickmark_cat, url, name))
quickmark_manager.removed.connect(_on_quickmark_removed)
bookmark_manager = objreg.get('bookmark-manager')
bookmarks = bookmark_manager.marks.items()
for bm_url, bm_title in bookmarks:
_model.new_item(_bookmark_cat, bm_url, bm_title)
bookmark_manager.added.connect(
lambda name, url: _model.new_item(_bookmark_cat, url, name))
bookmark_manager.removed.connect(_on_bookmark_removed)
history = objreg.get('web-history')
max_history = config.get('completion', 'web-history-max-items')
for entry in utils.newest_slice(history, max_history):
if not entry.redirect:
_add_history_entry(entry)
history.add_completion_item.connect(_on_history_item_added)
history.cleared.connect(_on_history_cleared)
objreg.get('config').changed.connect(_reformat_timestamps)
def url(): def url():
"""A _model which combines bookmarks, quickmarks and web history URLs. """A model which combines bookmarks, quickmarks and web history URLs.
Used for the `open` command. Used for the `open` command.
""" """
if not _model: urlcol = 0
_init() textcol = 1
return _model
model = sqlmodel.SqlCompletionModel(column_widths=(40, 50, 10),
columns_to_filter=[urlcol, textcol])
model.new_category('History')
model.new_category('Quickmarks')
model.new_category('Bookmarks')
return model

View File

@ -27,7 +27,7 @@ from hypothesis import strategies
from PyQt5.QtCore import QUrl from PyQt5.QtCore import QUrl
from qutebrowser.browser import history from qutebrowser.browser import history
from qutebrowser.utils import objreg, urlutils from qutebrowser.utils import objreg, urlutils, usertypes
from qutebrowser.misc import sql from qutebrowser.misc import sql