Fix memory leak in AnkiWebView (#1510)

This commit is contained in:
Hikaru Y 2021-11-29 11:31:37 +09:00 committed by GitHub
parent 627f910635
commit d2cbd15bbe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 21 additions and 1 deletions

View File

@ -91,6 +91,15 @@ def show(mw: aqt.AnkiQt) -> QDialog:
abt.buttonBox.addButton(btn, QDialogButtonBox.ButtonRole.ActionRole) abt.buttonBox.addButton(btn, QDialogButtonBox.ButtonRole.ActionRole)
abt.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setFocus() abt.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setFocus()
# WebView cleanup
######################################################################
def on_dialog_destroyed() -> None:
abt.label.cleanup()
abt.label = None
qconnect(dialog.destroyed, on_dialog_destroyed)
# WebView contents # WebView contents
###################################################################### ######################################################################
abouttext = "<center><img src='/_anki/imgs/anki-logo-thin.png'></center>" abouttext = "<center><img src='/_anki/imgs/anki-logo-thin.png'></center>"

View File

@ -77,6 +77,7 @@ class CardInfoDialog(QDialog):
def reject(self) -> None: def reject(self) -> None:
if self._on_close: if self._on_close:
self._on_close() self._on_close()
self.web.cleanup()
self.web = None self.web = None
saveGeom(self, self.GEOMETRY_KEY) saveGeom(self, self.GEOMETRY_KEY)
return QDialog.reject(self) return QDialog.reject(self)

View File

@ -120,6 +120,7 @@ class Previewer(QDialog):
def _on_close(self) -> None: def _on_close(self) -> None:
self._open = False self._open = False
self._close_callback() self._close_callback()
self._web.cleanup()
self._web = None self._web = None
def _setup_web_view(self) -> None: def _setup_web_view(self) -> None:

View File

@ -65,6 +65,7 @@ class ChangeNotetypeDialog(QDialog):
self.setWindowTitle(tr.browsing_change_notetype()) self.setWindowTitle(tr.browsing_change_notetype())
def reject(self) -> None: def reject(self) -> None:
self.web.cleanup()
self.web = None self.web = None
saveGeom(self, self.TITLE) saveGeom(self, self.TITLE)
QDialog.reject(self) QDialog.reject(self)

View File

@ -825,6 +825,7 @@ class CardLayout(QDialog):
av_player.stop_and_clear_queue() av_player.stop_and_clear_queue()
saveGeom(self, "CardLayout") saveGeom(self, "CardLayout")
saveSplitter(self.mainArea, "CardLayoutMainArea") saveSplitter(self.mainArea, "CardLayoutMainArea")
self.preview_web.cleanup()
self.preview_web = None self.preview_web = None
self.model = None self.model = None
self.rendered_card = None self.rendered_card = None

View File

@ -60,6 +60,7 @@ class DeckOptionsDialog(QDialog):
gui_hooks.deck_options_did_load(self) gui_hooks.deck_options_did_load(self)
def reject(self) -> None: def reject(self) -> None:
self.web.cleanup()
self.web = None self.web = None
saveGeom(self, self.TITLE) saveGeom(self, self.TITLE)
QDialog.reject(self) QDialog.reject(self)

View File

@ -586,6 +586,7 @@ noteEditorPromise.then(noteEditor => noteEditor.toolbar.toolbar.appendGroup({{
def cleanup(self) -> None: def cleanup(self) -> None:
self.set_note(None) self.set_note(None)
# prevent any remaining evalWithCallback() events from firing after C++ object deleted # prevent any remaining evalWithCallback() events from firing after C++ object deleted
self.web.cleanup()
self.web = None self.web = None
# legacy # legacy

View File

@ -36,6 +36,7 @@ class EmptyCardsDialog(QDialog):
def __init__(self, mw: aqt.main.AnkiQt, report: EmptyCardsReport) -> None: def __init__(self, mw: aqt.main.AnkiQt, report: EmptyCardsReport) -> None:
super().__init__(mw) super().__init__(mw)
self.mw = mw.weakref() self.mw = mw.weakref()
self.mw.garbage_collect_on_dialog_finish(self)
self.report = report self.report = report
self.form = aqt.forms.emptycards.Ui_Dialog() self.form = aqt.forms.emptycards.Ui_Dialog()
self.form.setupUi(self) self.form.setupUi(self)
@ -58,6 +59,8 @@ class EmptyCardsDialog(QDialog):
self.form.webview.stdHtml(style + html, context=self) self.form.webview.stdHtml(style + html, context=self)
def on_finished(code: Any) -> None: def on_finished(code: Any) -> None:
self.form.webview.cleanup()
self.form.webview = None
saveGeom(self, "emptycards") saveGeom(self, "emptycards")
qconnect(self.finished, on_finished) qconnect(self.finished, on_finished)

View File

@ -54,6 +54,7 @@ class NewDeckStats(QDialog):
self.activateWindow() self.activateWindow()
def reject(self) -> None: def reject(self) -> None:
self.form.web.cleanup()
self.form.web = None self.form.web = None
saveGeom(self, self.name) saveGeom(self, self.name)
aqt.dialogs.markClosed("NewDeckStats") aqt.dialogs.markClosed("NewDeckStats")
@ -144,6 +145,7 @@ class DeckStats(QDialog):
self.activateWindow() self.activateWindow()
def reject(self) -> None: def reject(self) -> None:
self.form.web.cleanup()
self.form.web = None self.form.web = None
saveGeom(self, self.name) saveGeom(self, self.name)
aqt.dialogs.markClosed("DeckStats") aqt.dialogs.markClosed("DeckStats")

View File

@ -671,7 +671,7 @@ document.head.appendChild(style);
self._domReady = False self._domReady = False
self._page.setContent(cast(QByteArray, bytes("", "ascii"))) self._page.setContent(cast(QByteArray, bytes("", "ascii")))
def __del__(self) -> None: def cleanup(self) -> None:
try: try:
from aqt import mw from aqt import mw
except ImportError: except ImportError: