From 9ff37d9baaed4895b9edfc428424f588d6c56dbf Mon Sep 17 00:00:00 2001 From: Ren Tatsumoto Date: Sun, 5 Sep 2021 13:20:27 +0300 Subject: [PATCH] Add a hook for modifiying pasted MIME data --- qt/aqt/editor.py | 32 ++++++++++++-------------------- qt/tools/genhooks_gui.py | 25 +++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 20 deletions(-) diff --git a/qt/aqt/editor.py b/qt/aqt/editor.py index 8ff59aaa8..1ec8137cf 100644 --- a/qt/aqt/editor.py +++ b/qt/aqt/editor.py @@ -863,13 +863,12 @@ $editorToolbar.then(({{ toolbar }}) => toolbar.appendGroup({{ self.web.eval(f"pasteHTML({json.dumps(html)}, {json.dumps(internal)}, {ext});") gui_hooks.editor_did_paste(self, html, internal, extended) - def doDrop(self, html: str, internal: bool, extended: bool = False) -> None: + def doDrop(self, html: str, internal: bool, extended: bool, cursor_pos: QPoint) -> None: def pasteIfField(ret: bool) -> None: if ret: self.doPaste(html, internal, extended) - p = self.web.mapFromGlobal(QCursor.pos()) - self.web.evalWithCallback(f"focusIfField({p.x()}, {p.y()});", pasteIfField) + self.web.evalWithCallback(f"focusIfField({cursor_pos.x()}, {cursor_pos.y()});", pasteIfField) def onPaste(self) -> None: self.web.onPaste() @@ -1138,30 +1137,34 @@ class EditorWebView(AnkiWebView): def dropEvent(self, evt: QDropEvent) -> None: extended = self._wantsExtendedPaste() mime = evt.mimeData() + cursor_pos = self.mapFromGlobal(QCursor.pos()) if evt.source() and mime.hasHtml(): # don't filter html from other fields html, internal = mime.html(), True else: - html, internal = self._processMime(mime, extended) + html, internal = self._processMime(mime, extended, drop_event=True) if not html: return - self.editor.doDrop(html, internal, extended) + self.editor.doDrop(html, internal, extended, cursor_pos) # returns (html, isInternal) - def _processMime(self, mime: QMimeData, extended: bool = False) -> Tuple[str, bool]: + def _processMime(self, mime: QMimeData, extended: bool = False, drop_event: bool = False) -> Tuple[str, bool]: # print("html=%s image=%s urls=%s txt=%s" % ( # mime.hasHtml(), mime.hasImage(), mime.hasUrls(), mime.hasText())) # print("html", mime.html()) # print("urls", mime.urls()) # print("text", mime.text()) + internal = mime.html().startswith("") + + mime = gui_hooks.editor_will_process_mime(self, mime, internal, extended, drop_event) + # try various content types in turn - html, internal = self._processHtml(mime) - if html: - return html, internal + if mime.hasHtml(): + return mime.html().replace("", ''), internal # favour url if it's a local link if mime.hasUrls() and mime.urls()[0].toString().startswith("file://"): @@ -1227,17 +1230,6 @@ class EditorWebView(AnkiWebView): processed.pop() return "".join(processed) - def _processHtml(self, mime: QMimeData) -> Tuple[Optional[str], bool]: - if not mime.hasHtml(): - return None, False - html = mime.html() - - # no filtering required for internal pastes - if html.startswith(""): - return html[11:], True - - return html, False - def _processImage(self, mime: QMimeData, extended: bool = False) -> Optional[str]: if not mime.hasImage(): return None diff --git a/qt/tools/genhooks_gui.py b/qt/tools/genhooks_gui.py index 0387bca7f..3a626ef06 100644 --- a/qt/tools/genhooks_gui.py +++ b/qt/tools/genhooks_gui.py @@ -864,6 +864,31 @@ gui_hooks.webview_did_inject_style_into_page.append(mytest) ], doc="""Called after some data is pasted by python into an editor field.""", ), + Hook( + name="editor_will_process_mime", + args=[ + "editor_web_view: aqt.editor.EditorWebView", + "mime: QMimeData", + "internal: bool", + "extended: bool", + "drop_event: bool", + ], + return_type="QMimeData", + doc=""" + Used to modify MIME data stored in the clipboard after a drop or a paste. + Called after the user pastes or drag-and-drops something to Anki + before Anki processes the data. + + The function should return a new or existing QMimeData object. + + "mime" contains the corresponding QMimeData object. + "internal" indicates whether the drop or paste is performed between Anki fields. + Most likely you want to skip processing if "internal" was set to True. + "extended" indicates whether the user requested an extended paste. + "drop_event" indicates whether the event was triggered by a drag-and-drop + or by a right-click paste. + """, + ), # Tag ################### Hook(name="tag_editor_did_process_key", args=["tag_edit: TagEdit", "evt: QEvent"]),