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 BrowserPreviewer as PreviewDialog
from aqt.previewer import Previewer from aqt.previewer import Previewer
from aqt.qt import * from aqt.qt import *
from aqt.sidebar import SidebarTreeView from aqt.sidebar import SidebarSearchBar, SidebarTreeView
from aqt.theme import theme_manager from aqt.theme import theme_manager
from aqt.utils import ( from aqt.utils import (
TR, TR,
@ -912,6 +912,17 @@ QTableView {{ gridline-color: {grid} }}
self.sidebar = SidebarTreeView(self) self.sidebar = SidebarTreeView(self)
self.sidebarTree = self.sidebar # legacy alias self.sidebarTree = self.sidebar # legacy alias
dw.setWidget(self.sidebar) 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.setFloating(False)
self.sidebarDockWidget.setTitleBarWidget(QWidget()) self.sidebarDockWidget.setTitleBarWidget(QWidget())
@ -921,12 +932,19 @@ QTableView {{ gridline-color: {grid} }}
# UI is more responsive # UI is more responsive
self.mw.progress.timer(10, self.sidebar.refresh, False) self.mw.progress.timer(10, self.sidebar.refresh, False)
def focusSidebar(self) -> None: def showSidebar(self) -> None:
# workaround for PyQt focus bug # workaround for PyQt focus bug
self.editor.hideCompleters() self.editor.hideCompleters()
self.sidebarDockWidget.setVisible(True) self.sidebarDockWidget.setVisible(True)
def focusSidebar(self) -> None:
self.showSidebar()
self.sidebar.setFocus() self.sidebar.setFocus()
def focusSidebarSearchBar(self) -> None:
self.showSidebar()
self.sidebar.searchBar.setFocus()
# legacy # legacy
def maybeRefreshSidebar(self) -> None: def maybeRefreshSidebar(self) -> None:
self.sidebar.refresh() self.sidebar.refresh()

View file

@ -4,6 +4,8 @@
from __future__ import annotations from __future__ import annotations
import copy
import re
from concurrent.futures import Future from concurrent.futures import Future
from enum import Enum from enum import Enum
from typing import Iterable, List, Optional from typing import Iterable, List, Optional
@ -177,6 +179,49 @@ class SidebarModel(QAbstractItemModel):
# then ourselves # then ourselves
tree.setExpanded(parent, True) 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): class SidebarTreeView(QTreeView):
def __init__(self, browser: aqt.browser.Browser) -> None: def __init__(self, browser: aqt.browser.Browser) -> None:
@ -222,6 +267,7 @@ class SidebarTreeView(QTreeView):
def on_done(fut: Future): def on_done(fut: Future):
root = fut.result() root = fut.result()
model = SidebarModel(root) model = SidebarModel(root)
self.flattened_model = model.flattened()
self.setModel(model) self.setModel(model)
model.expandWhereNeccessary(self) model.expandWhereNeccessary(self)
@ -359,6 +405,7 @@ class SidebarTreeView(QTreeView):
not node.collapsed, not node.collapsed,
item_type=SidebarItemType.DECK, item_type=SidebarItemType.DECK,
id=node.deck_id, id=node.deck_id,
full_name=head + node.name,
) )
root.addChild(item) root.addChild(item)
newhead = head + node.name + "::" newhead = head + node.name + "::"
@ -384,6 +431,7 @@ class SidebarTreeView(QTreeView):
":/icons/notetype.svg", ":/icons/notetype.svg",
self._template_filter(nt["name"], c), self._template_filter(nt["name"], c),
item_type=SidebarItemType.TEMPLATE, item_type=SidebarItemType.TEMPLATE,
full_name=nt["name"] + "::" + tmpl["name"],
) )
item.addChild(child) item.addChild(child)