Merge pull request #447 from glutanimate/browser-sidebar-tree-hooks

Add browser_will_build_tree filter
This commit is contained in:
Damien Elmes 2020-02-16 08:36:28 +10:00 committed by GitHub
commit 0ec3bbe1af
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 175 additions and 5 deletions

View file

@ -11,6 +11,7 @@ import sre_constants
import time import time
import unicodedata import unicodedata
from dataclasses import dataclass from dataclasses import dataclass
from enum import Enum
from operator import itemgetter from operator import itemgetter
from typing import Callable, List, Optional, Union from typing import Callable, List, Optional, Union
@ -418,6 +419,15 @@ class StatusDelegate(QItemDelegate):
###################################################################### ######################################################################
class SidebarStage(Enum):
ROOT = 0
STANDARD = 1
FAVORITES = 2
DECKS = 3
MODELS = 4
TAGS = 5
class SidebarItem: class SidebarItem:
def __init__( def __init__(
self, self,
@ -1085,11 +1095,27 @@ by clicking on one on the left."""
def buildTree(self) -> SidebarItem: def buildTree(self) -> SidebarItem:
root = SidebarItem("", "") root = SidebarItem("", "")
self._stdTree(root)
self._favTree(root) handled = gui_hooks.browser_will_build_tree(
self._decksTree(root) False, root, SidebarStage.ROOT, self
self._modelTree(root) )
self._userTagTree(root) if handled:
return root
for stage, builder in zip(
list(SidebarStage)[1:],
(
self._stdTree,
self._favTree,
self._decksTree,
self._modelTree,
self._userTagTree,
),
):
handled = gui_hooks.browser_will_build_tree(False, root, stage, self)
if not handled and builder:
builder(root)
return root return root
def _stdTree(self, root) -> None: def _stdTree(self, root) -> None:

View file

@ -203,6 +203,105 @@ class _BrowserMenusDidInitHook:
browser_menus_did_init = _BrowserMenusDidInitHook() browser_menus_did_init = _BrowserMenusDidInitHook()
class _BrowserWillBuildTreeFilter:
"""Used to add or replace items in the browser sidebar tree
'tree' is the root SidebarItem that all other items are added to.
'stage' is an enum describing the different construction stages of
the sidebar tree at which you can interject your changes.
The different values can be inspected by looking at
aqt.browser.SidebarStage.
If you want Anki to proceed with the construction of the tree stage
in question after your have performed your changes or additions,
return the 'handled' boolean unchanged.
On the other hand, if you want to prevent Anki from adding its own
items at a particular construction stage (e.g. in case your add-on
implements its own version of that particular stage), return 'True'.
If you return 'True' at SidebarStage.ROOT, the sidebar will not be
populated by any of the other construction stages. For any other stage
the tree construction will just continue as usual.
For example, if your code wishes to replace the tag tree, you could do:
def on_browser_will_build_tree(handled, root, stage, browser):
if stage != SidebarStage.TAGS:
# not at tag tree building stage, pass on
return handled
# your tag tree construction code
# root.addChild(...)
# your code handled tag tree construction, no need for Anki
# or other add-ons to build the tag tree
return True
"""
_hooks: List[
Callable[
[
bool,
"aqt.browser.SidebarItem",
"aqt.browser.SidebarStage",
"aqt.browser.Browser",
],
bool,
]
] = []
def append(
self,
cb: Callable[
[
bool,
"aqt.browser.SidebarItem",
"aqt.browser.SidebarStage",
"aqt.browser.Browser",
],
bool,
],
) -> None:
"""(handled: bool, tree: aqt.browser.SidebarItem, stage: aqt.browser.SidebarStage, browser: aqt.browser.Browser)"""
self._hooks.append(cb)
def remove(
self,
cb: Callable[
[
bool,
"aqt.browser.SidebarItem",
"aqt.browser.SidebarStage",
"aqt.browser.Browser",
],
bool,
],
) -> None:
if cb in self._hooks:
self._hooks.remove(cb)
def __call__(
self,
handled: bool,
tree: aqt.browser.SidebarItem,
stage: aqt.browser.SidebarStage,
browser: aqt.browser.Browser,
) -> bool:
for filter in self._hooks:
try:
handled = filter(handled, tree, stage, browser)
except:
# if the hook fails, remove it
self._hooks.remove(filter)
raise
return handled
browser_will_build_tree = _BrowserWillBuildTreeFilter()
class _BrowserWillShowContextMenuHook: class _BrowserWillShowContextMenuHook:
_hooks: List[Callable[["aqt.browser.Browser", QMenu], None]] = [] _hooks: List[Callable[["aqt.browser.Browser", QMenu], None]] = []

View file

@ -98,6 +98,51 @@ hooks = [
args=["browser: aqt.browser.Browser"], args=["browser: aqt.browser.Browser"],
legacy_hook="browser.rowChanged", legacy_hook="browser.rowChanged",
), ),
Hook(
name="browser_will_build_tree",
args=[
"handled: bool",
"tree: aqt.browser.SidebarItem",
"stage: aqt.browser.SidebarStage",
"browser: aqt.browser.Browser",
],
return_type="bool",
doc="""Used to add or replace items in the browser sidebar tree
'tree' is the root SidebarItem that all other items are added to.
'stage' is an enum describing the different construction stages of
the sidebar tree at which you can interject your changes.
The different values can be inspected by looking at
aqt.browser.SidebarStage.
If you want Anki to proceed with the construction of the tree stage
in question after your have performed your changes or additions,
return the 'handled' boolean unchanged.
On the other hand, if you want to prevent Anki from adding its own
items at a particular construction stage (e.g. in case your add-on
implements its own version of that particular stage), return 'True'.
If you return 'True' at SidebarStage.ROOT, the sidebar will not be
populated by any of the other construction stages. For any other stage
the tree construction will just continue as usual.
For example, if your code wishes to replace the tag tree, you could do:
def on_browser_will_build_tree(handled, root, stage, browser):
if stage != SidebarStage.TAGS:
# not at tag tree building stage, pass on
return handled
# your tag tree construction code
# root.addChild(...)
# your code handled tag tree construction, no need for Anki
# or other add-ons to build the tag tree
return True
""",
),
# States # States
################### ###################
Hook( Hook(