Add a hook for modifiying pasted MIME data

This commit is contained in:
Ren Tatsumoto 2021-09-05 13:20:27 +03:00
parent e5409a25b5
commit 9ff37d9baa
2 changed files with 37 additions and 20 deletions

View file

@ -863,13 +863,12 @@ $editorToolbar.then(({{ toolbar }}) => toolbar.appendGroup({{
self.web.eval(f"pasteHTML({json.dumps(html)}, {json.dumps(internal)}, {ext});") self.web.eval(f"pasteHTML({json.dumps(html)}, {json.dumps(internal)}, {ext});")
gui_hooks.editor_did_paste(self, html, internal, extended) 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: def pasteIfField(ret: bool) -> None:
if ret: if ret:
self.doPaste(html, internal, extended) self.doPaste(html, internal, extended)
p = self.web.mapFromGlobal(QCursor.pos()) self.web.evalWithCallback(f"focusIfField({cursor_pos.x()}, {cursor_pos.y()});", pasteIfField)
self.web.evalWithCallback(f"focusIfField({p.x()}, {p.y()});", pasteIfField)
def onPaste(self) -> None: def onPaste(self) -> None:
self.web.onPaste() self.web.onPaste()
@ -1138,30 +1137,34 @@ class EditorWebView(AnkiWebView):
def dropEvent(self, evt: QDropEvent) -> None: def dropEvent(self, evt: QDropEvent) -> None:
extended = self._wantsExtendedPaste() extended = self._wantsExtendedPaste()
mime = evt.mimeData() mime = evt.mimeData()
cursor_pos = self.mapFromGlobal(QCursor.pos())
if evt.source() and mime.hasHtml(): if evt.source() and mime.hasHtml():
# don't filter html from other fields # don't filter html from other fields
html, internal = mime.html(), True html, internal = mime.html(), True
else: else:
html, internal = self._processMime(mime, extended) html, internal = self._processMime(mime, extended, drop_event=True)
if not html: if not html:
return return
self.editor.doDrop(html, internal, extended) self.editor.doDrop(html, internal, extended, cursor_pos)
# returns (html, isInternal) # 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" % ( # print("html=%s image=%s urls=%s txt=%s" % (
# mime.hasHtml(), mime.hasImage(), mime.hasUrls(), mime.hasText())) # mime.hasHtml(), mime.hasImage(), mime.hasUrls(), mime.hasText()))
# print("html", mime.html()) # print("html", mime.html())
# print("urls", mime.urls()) # print("urls", mime.urls())
# print("text", mime.text()) # print("text", mime.text())
internal = mime.html().startswith("<!--anki-->")
mime = gui_hooks.editor_will_process_mime(self, mime, internal, extended, drop_event)
# try various content types in turn # try various content types in turn
html, internal = self._processHtml(mime) if mime.hasHtml():
if html: return mime.html().replace("<!--anki-->", ''), internal
return html, internal
# favour url if it's a local link # favour url if it's a local link
if mime.hasUrls() and mime.urls()[0].toString().startswith("file://"): if mime.hasUrls() and mime.urls()[0].toString().startswith("file://"):
@ -1227,17 +1230,6 @@ class EditorWebView(AnkiWebView):
processed.pop() processed.pop()
return "".join(processed) 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("<!--anki-->"):
return html[11:], True
return html, False
def _processImage(self, mime: QMimeData, extended: bool = False) -> Optional[str]: def _processImage(self, mime: QMimeData, extended: bool = False) -> Optional[str]:
if not mime.hasImage(): if not mime.hasImage():
return None return None

View file

@ -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.""", 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 # Tag
################### ###################
Hook(name="tag_editor_did_process_key", args=["tag_edit: TagEdit", "evt: QEvent"]), Hook(name="tag_editor_did_process_key", args=["tag_edit: TagEdit", "evt: QEvent"]),