Add search bar to the sidebar

https://github.com/ankitects/help-wanted/issues/6
This commit is contained in:
abdo 2021-01-27 01:35:40 +03:00
parent 322788133b
commit 208c713e39
2 changed files with 68 additions and 2 deletions

View file

@ -35,7 +35,7 @@ from aqt.main import ResetReason
from aqt.previewer import BrowserPreviewer as PreviewDialog
from aqt.previewer import Previewer
from aqt.qt import *
from aqt.sidebar import SidebarTreeView
from aqt.sidebar import SidebarSearchBar, SidebarTreeView
from aqt.theme import theme_manager
from aqt.utils import (
TR,
@ -912,6 +912,17 @@ QTableView {{ gridline-color: {grid} }}
self.sidebar = SidebarTreeView(self)
self.sidebarTree = self.sidebar # legacy alias
dw.setWidget(self.sidebar)
self.sidebar.searchBar = searchBar = SidebarSearchBar(self.sidebar)
qconnect(
QShortcut(QKeySequence("Ctrl+Shift+B"), self).activated,
self.focusSidebarSearchBar,
)
l = QVBoxLayout()
l.addWidget(searchBar)
l.addWidget(self.sidebar)
w = QWidget()
w.setLayout(l)
dw.setWidget(w)
self.sidebarDockWidget.setFloating(False)
self.sidebarDockWidget.setTitleBarWidget(QWidget())
@ -921,12 +932,19 @@ QTableView {{ gridline-color: {grid} }}
# UI is more responsive
self.mw.progress.timer(10, self.sidebar.refresh, False)
def focusSidebar(self) -> None:
def showSidebar(self) -> None:
# workaround for PyQt focus bug
self.editor.hideCompleters()
self.sidebarDockWidget.setVisible(True)
def focusSidebar(self) -> None:
self.showSidebar()
self.sidebar.setFocus()
def focusSidebarSearchBar(self) -> None:
self.showSidebar()
self.sidebar.searchBar.setFocus()
# legacy
def maybeRefreshSidebar(self) -> None:
self.sidebar.refresh()

View file

@ -4,6 +4,8 @@
from __future__ import annotations
import copy
import re
from concurrent.futures import Future
from enum import Enum
from typing import Iterable, List, Optional
@ -177,6 +179,49 @@ class SidebarModel(QAbstractItemModel):
# then ourselves
tree.setExpanded(parent, True)
def flattened(self) -> SidebarModel:
"Returns a flattened representation of the model."
root = SidebarItem("", "", item_type=SidebarItemType.ROOT)
def flatten_tree(children: Iterable[SidebarItem]):
for child in children:
child.name = child.full_name
root.addChild(child)
flatten_tree(child.children)
child.children = []
flatten_tree(copy.deepcopy(self.root.children))
return SidebarModel(root)
class SidebarSearchBar(QLineEdit):
def __init__(self, sidebar):
QLineEdit.__init__(self, sidebar)
self.sidebar = sidebar
qconnect(self.textChanged, self.onTextChanged)
def onTextChanged(self, text: str):
if text == "":
self.sidebar.refresh()
else:
# show matched items in the sidebar
root = SidebarItem("", "", item_type=SidebarItemType.ROOT)
pattern = re.compile("(?i).*{}.*".format(re.escape(text)))
for item in self.sidebar.flattened_model.root.children:
if pattern.match(item.name) or pattern.match(item.full_name):
root.addChild(item)
self.sidebar.setModel(SidebarModel(root))
def keyPressEvent(self, evt):
if evt.key() in (Qt.Key_Up, Qt.Key_Down):
self.sidebar.setFocus()
elif evt.key() in (Qt.Key_Enter, Qt.Key_Return):
self.onTextChanged(self.text())
else:
QLineEdit.keyPressEvent(self, evt)
class SidebarTreeView(QTreeView):
def __init__(self, browser: aqt.browser.Browser) -> None:
@ -222,6 +267,7 @@ class SidebarTreeView(QTreeView):
def on_done(fut: Future):
root = fut.result()
model = SidebarModel(root)
self.flattened_model = model.flattened()
self.setModel(model)
model.expandWhereNeccessary(self)
@ -359,6 +405,7 @@ class SidebarTreeView(QTreeView):
not node.collapsed,
item_type=SidebarItemType.DECK,
id=node.deck_id,
full_name=head + node.name,
)
root.addChild(item)
newhead = head + node.name + "::"
@ -384,6 +431,7 @@ class SidebarTreeView(QTreeView):
":/icons/notetype.svg",
self._template_filter(nt["name"], c),
item_type=SidebarItemType.TEMPLATE,
full_name=nt["name"] + "::" + tmpl["name"],
)
item.addChild(child)