mirror of
https://github.com/Yubico/yubioath-flutter.git
synced 2025-01-03 15:47:52 +03:00
Merge pull request #99 from tycho/add-search-box.
This commit is contained in:
commit
4e25a257ec
@ -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..."
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user