diff --git a/qt/aqt/addons.py b/qt/aqt/addons.py index 826fe4b0c..ecd7c56dd 100644 --- a/qt/aqt/addons.py +++ b/qt/aqt/addons.py @@ -26,6 +26,7 @@ import aqt import aqt.forms from anki.httpclient import HttpClient from anki.lang import _, ngettext +from aqt import gui_hooks from aqt.qt import * from aqt.utils import ( TR, @@ -1284,15 +1285,11 @@ class ConfigEditor(QDialog): self.form.scrollArea.setVisible(False) def updateText(self, conf): - self.form.editor.setPlainText( - json.dumps( - conf, - ensure_ascii=False, - sort_keys=True, - indent=4, - separators=(",", ": "), - ) + text = json.dumps( + conf, ensure_ascii=False, sort_keys=True, indent=4, separators=(",", ": "), ) + text = gui_hooks.addon_config_editor_will_display_json(text) + self.form.editor.setPlainText(text) def onClose(self): saveGeom(self, "addonconf") @@ -1304,6 +1301,7 @@ class ConfigEditor(QDialog): def accept(self): txt = self.form.editor.toPlainText() + txt = gui_hooks.addon_config_editor_will_save_json(txt) try: new_conf = json.loads(txt) except Exception as e: diff --git a/qt/aqt/gui_hooks.py b/qt/aqt/gui_hooks.py index bb808cd75..fded1c1c8 100644 --- a/qt/aqt/gui_hooks.py +++ b/qt/aqt/gui_hooks.py @@ -75,6 +75,66 @@ class _AddCardsWillShowHistoryMenuHook: add_cards_will_show_history_menu = _AddCardsWillShowHistoryMenuHook() +class _AddonConfigEditorWillDisplayJsonFilter: + """Allows changing the text of the json configuration before actually + displaying it to the user. For example, you can replace "\n" by + some actual new line. Then you can replace the new lines by "\n" + while reading the file and let the user uses real new line in + string instead of its encoding.""" + + _hooks: List[Callable[[str], str]] = [] + + def append(self, cb: Callable[[str], str]) -> None: + """(text: str)""" + self._hooks.append(cb) + + def remove(self, cb: Callable[[str], str]) -> None: + if cb in self._hooks: + self._hooks.remove(cb) + + def __call__(self, text: str) -> str: + for filter in self._hooks: + try: + text = filter(text) + except: + # if the hook fails, remove it + self._hooks.remove(filter) + raise + return text + + +addon_config_editor_will_display_json = _AddonConfigEditorWillDisplayJsonFilter() + + +class _AddonConfigEditorWillSaveJsonFilter: + """Allows changing the text of the json configuration that was + received from the user before actually reading it. For + example, you can replace new line in strings by some "\n".""" + + _hooks: List[Callable[[str], str]] = [] + + def append(self, cb: Callable[[str], str]) -> None: + """(text: str)""" + self._hooks.append(cb) + + def remove(self, cb: Callable[[str], str]) -> None: + if cb in self._hooks: + self._hooks.remove(cb) + + def __call__(self, text: str) -> str: + for filter in self._hooks: + try: + text = filter(text) + except: + # if the hook fails, remove it + self._hooks.remove(filter) + raise + return text + + +addon_config_editor_will_save_json = _AddonConfigEditorWillSaveJsonFilter() + + class _AvPlayerDidBeginPlayingHook: _hooks: List[Callable[["aqt.sound.Player", "anki.sound.AVTag"], None]] = [] diff --git a/qt/tools/genhooks_gui.py b/qt/tools/genhooks_gui.py index bc1542984..1147c0653 100644 --- a/qt/tools/genhooks_gui.py +++ b/qt/tools/genhooks_gui.py @@ -452,6 +452,26 @@ def emptyNewCard(): args=["player: aqt.sound.Player", "tag: anki.sound.AVTag"], ), Hook(name="av_player_did_end_playing", args=["player: aqt.sound.Player"]), + # Addon + ################### + Hook( + name="addon_config_editor_will_display_json", + args=["text: str"], + return_type="str", + doc="""Allows changing the text of the json configuration before actually + displaying it to the user. For example, you can replace "\\\\n" by + some actual new line. Then you can replace the new lines by "\\\\n" + while reading the file and let the user uses real new line in + string instead of its encoding.""", + ), + Hook( + name="addon_config_editor_will_save_json", + args=["text: str"], + return_type="str", + doc="""Allows changing the text of the json configuration that was + received from the user before actually reading it. For + example, you can replace new line in strings by some "\\\\n".""", + ), # Other ################### Hook(