Merge pull request #99 from tycho/add-search-box.

This commit is contained in:
Dain Nilsson 2016-09-23 17:06:53 +02:00
commit 4e25a257ec
2 changed files with 79 additions and 2 deletions

View File

@ -53,6 +53,7 @@ action_quit = "&Quit"
password = "Password"
settings = "Settings"
advanced = "Advanced"
search = "Search"
pass_required = "Password required"
remember = "Remember password"
no_key = "Insert a YubiKey..."

View File

@ -74,6 +74,56 @@ class TimeleftBar(QtGui.QProgressBar):
self.expired.emit()
class SearchBox(QtGui.QWidget):
def __init__(self, codes):
super(SearchBox, self).__init__()
self._codeswidget = codes
layout = QtGui.QHBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
self._model = QtGui.QStringListModel()
self._completer = QtGui.QCompleter()
self._completer.setModel(self._model)
self._completer.setCompletionMode(QtGui.QCompleter.InlineCompletion)
self._completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
self._lineedit = QtGui.QLineEdit()
self._lineedit.setPlaceholderText(m.search)
self._lineedit.setCompleter(self._completer)
self._lineedit.textChanged.connect(self._text_changed)
layout.addWidget(self._lineedit)
self._shortcut_focus = QtGui.QShortcut(
QtGui.QKeySequence.Find,
self._lineedit, self._set_focus)
self._shortcut_clear = QtGui.QShortcut(
QtGui.QKeySequence(self.tr("Esc")),
self._lineedit, self._lineedit.clear)
self._timer = QtCore.QTimer()
self._timer.setSingleShot(True)
self._timer.setInterval(300)
self._timer.timeout.connect(self._filter_changed)
def _set_focus(self):
self._lineedit.setFocus()
self._lineedit.selectAll()
def _text_changed(self, query):
self._timer.stop()
self._timer.start()
def _filter_changed(self):
search_filter = self._lineedit.text()
self._codeswidget.set_search_filter(search_filter)
def set_string_list(self, strings):
self._model.setStringList(strings)
class CodeMenu(QtGui.QMenu):
def __init__(self, parent):
@ -190,7 +240,7 @@ class Code(QtGui.QWidget):
class CodesList(QtGui.QWidget):
def __init__(self, timer, credentials=[], on_change=None):
def __init__(self, timer, credentials=[], on_change=None, search_filter=None):
super(CodesList, self).__init__()
layout = QtGui.QVBoxLayout(self)
@ -198,6 +248,9 @@ class CodesList(QtGui.QWidget):
layout.setSpacing(0)
for cred in credentials:
if search_filter is not None and \
search_filter.lower() not in cred.cred.name.lower():
continue
layout.addWidget(Code(cred, timer, on_change))
line = QtGui.QFrame()
line.setFrameShape(QtGui.QFrame.HLine)
@ -223,12 +276,15 @@ class CodesWidget(QtGui.QWidget):
controller.refreshed.connect(self.refresh)
controller.timer.time_changed.connect(self.refresh_timer)
self._filter = None
self._build_ui()
self.refresh()
self.refresh_timer()
def _build_ui(self):
layout = QtGui.QVBoxLayout(self)
self._timeleft = TimeleftBar()
layout.addWidget(self._timeleft)
@ -241,6 +297,9 @@ class CodesWidget(QtGui.QWidget):
self._scroll_area.setWidget(QtGui.QWidget())
layout.addWidget(self._scroll_area)
self._searchbox = SearchBox(self)
layout.addWidget(self._searchbox)
def refresh_timer(self, timestamp=None):
if timestamp is None:
timestamp = self._controller.timer.time
@ -249,11 +308,28 @@ class CodesWidget(QtGui.QWidget):
else:
self._timeleft.set_timeleft(0)
def rebuild_completions(self):
creds = self._controller.credentials
stringlist = set()
if not creds:
return
for cred in creds:
cred_name = cred.cred.name
stringlist |= set(cred_name.split(':', 1))
self._searchbox.set_string_list(list(stringlist))
def set_search_filter(self, search_filter):
if len(search_filter) < 1:
search_filter = None
self._filter = search_filter
self.refresh()
def refresh(self):
self._scroll_area.takeWidget().deleteLater()
creds = self._controller.credentials
self.rebuild_completions()
self._scroll_area.setWidget(
CodesList(self._controller.timer, creds or [], self.refresh_timer))
CodesList(self._controller.timer, creds or [], self.refresh_timer, self._filter))
w = self._scroll_area.widget().minimumSizeHint().width()
w += self._scroll_area.verticalScrollBar().width()
self._scroll_area.setMinimumWidth(w)