diff --git a/qt/aqt/gui_hooks.py b/qt/aqt/gui_hooks.py index 65b16e5f7..157bd3e80 100644 --- a/qt/aqt/gui_hooks.py +++ b/qt/aqt/gui_hooks.py @@ -2844,6 +2844,54 @@ class _UndoStateDidChangeHook: undo_state_did_change = _UndoStateDidChangeHook() +class _WebviewDidInjectStyleIntoPageHook: + '''Called after standard styling is injected into an external +html file, such as when loading the new graphs. You can use this hook to +mutate the DOM before the page is revealed. + +For example: + +def mytest(web: AnkiWebView): + page = os.path.basename(web.page().url().path()) + if page != "graphs.html": + return + web.eval( + """ + div = document.createElement("div"); + div.innerHTML = 'hello'; + document.body.appendChild(div); +""" + ) + +gui_hooks.webview_did_inject_style_into_page.append(mytest) +''' + + _hooks: List[Callable[[AnkiWebView], None]] = [] + + def append(self, cb: Callable[[AnkiWebView], None]) -> None: + """(webview: AnkiWebView)""" + self._hooks.append(cb) + + def remove(self, cb: Callable[[AnkiWebView], None]) -> None: + if cb in self._hooks: + self._hooks.remove(cb) + + def count(self) -> int: + return len(self._hooks) + + def __call__(self, webview: AnkiWebView) -> None: + for hook in self._hooks: + try: + hook(webview) + except: + # if the hook fails, remove it + self._hooks.remove(hook) + raise + + +webview_did_inject_style_into_page = _WebviewDidInjectStyleIntoPageHook() + + class _WebviewDidReceiveJsMessageFilter: """Used to handle pycmd() messages sent from Javascript. diff --git a/qt/aqt/webview.py b/qt/aqt/webview.py index 6a6c3193b..bf2933642 100644 --- a/qt/aqt/webview.py +++ b/qt/aqt/webview.py @@ -598,14 +598,15 @@ body {{ zoom: {zoom}; background: {background}; direction: {lang_dir}; {font} }} def inject_dynamic_style_and_show(self): "Add dynamic styling, and reveal." css = self.standard_css() + def after_style(arg): + gui_hooks.webview_did_inject_style_into_page(self) + self.show() self.evalWithCallback( f""" const style = document.createElement('style'); style.innerHTML = `{css}`; document.head.appendChild(style); -""", - lambda arg: self.show(), - ) +""", after_style) def load_ts_page(self, name: str) -> None: from aqt import mw diff --git a/qt/tools/genhooks_gui.py b/qt/tools/genhooks_gui.py index 1d7b3336b..c422f5b33 100644 --- a/qt/tools/genhooks_gui.py +++ b/qt/tools/genhooks_gui.py @@ -452,6 +452,29 @@ hooks = [ args=["webview: aqt.webview.AnkiWebView", "menu: QMenu"], legacy_hook="AnkiWebView.contextMenuEvent", ), + Hook( + name="webview_did_inject_style_into_page", + args=["webview: AnkiWebView"], + doc='''Called after standard styling is injected into an external +html file, such as when loading the new graphs. You can use this hook to +mutate the DOM before the page is revealed. + +For example: + +def mytest(web: AnkiWebView): + page = os.path.basename(web.page().url().path()) + if page != "graphs.html": + return + web.eval( + """ + div = document.createElement("div"); + div.innerHTML = 'hello'; + document.body.appendChild(div); +""" + ) + +gui_hooks.webview_did_inject_style_into_page.append(mytest) +'''), # Main ################### Hook(