mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
fix a bunch of qt typing issues uncovered by the following commit
This commit is contained in:
parent
75a0f165c6
commit
0c59c8b591
23 changed files with 198 additions and 139 deletions
|
@ -10,7 +10,7 @@ import os
|
|||
import sys
|
||||
import tempfile
|
||||
import traceback
|
||||
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
||||
from typing import Any, Callable, Dict, List, Optional, Tuple, Union, cast
|
||||
|
||||
import anki.lang
|
||||
from anki import version as _version
|
||||
|
@ -299,7 +299,7 @@ class AnkiApp(QApplication):
|
|||
if not sock.waitForReadyRead(self.TMOUT):
|
||||
sys.stderr.write(sock.errorString())
|
||||
return
|
||||
path = bytes(sock.readAll()).decode("utf8")
|
||||
path = bytes(cast(bytes, sock.readAll())).decode("utf8")
|
||||
self.appMsg.emit(path) # type: ignore
|
||||
sock.disconnectFromServer()
|
||||
|
||||
|
|
|
@ -715,7 +715,7 @@ class AddonsDialog(QDialog):
|
|||
gui_hooks.addons_dialog_will_show(self)
|
||||
self.show()
|
||||
|
||||
def dragEnterEvent(self, event: QEvent) -> None:
|
||||
def dragEnterEvent(self, event: QDragEnterEvent) -> None:
|
||||
mime = event.mimeData()
|
||||
if not mime.hasUrls():
|
||||
return None
|
||||
|
@ -724,7 +724,7 @@ class AddonsDialog(QDialog):
|
|||
if all(url.toLocalFile().endswith(ext) for url in urls):
|
||||
event.acceptProposedAction()
|
||||
|
||||
def dropEvent(self, event: QEvent) -> None:
|
||||
def dropEvent(self, event: QDropEvent) -> None:
|
||||
mime = event.mimeData()
|
||||
paths = []
|
||||
for url in mime.urls():
|
||||
|
@ -908,7 +908,7 @@ class AddonsDialog(QDialog):
|
|||
|
||||
|
||||
class GetAddons(QDialog):
|
||||
def __init__(self, dlg: QDialog) -> None:
|
||||
def __init__(self, dlg: AddonsDialog) -> None:
|
||||
QDialog.__init__(self, dlg)
|
||||
self.addonsDlg = dlg
|
||||
self.mgr = dlg.mgr
|
||||
|
@ -1079,7 +1079,9 @@ class DownloaderInstaller(QObject):
|
|||
|
||||
self.on_done = on_done
|
||||
|
||||
self.mgr.mw.progress.start(immediate=True, parent=self.parent())
|
||||
parent = self.parent()
|
||||
assert isinstance(parent, QWidget)
|
||||
self.mgr.mw.progress.start(immediate=True, parent=parent)
|
||||
self.mgr.mw.taskman.run_in_background(self._download_all, self._download_done)
|
||||
|
||||
def _progress_callback(self, up: int, down: int) -> None:
|
||||
|
@ -1438,7 +1440,7 @@ def prompt_to_update(
|
|||
|
||||
|
||||
class ConfigEditor(QDialog):
|
||||
def __init__(self, dlg: QDialog, addon: str, conf: Dict) -> None:
|
||||
def __init__(self, dlg: AddonsDialog, addon: str, conf: Dict) -> None:
|
||||
super().__init__(dlg)
|
||||
self.addon = addon
|
||||
self.conf = conf
|
||||
|
@ -1506,7 +1508,7 @@ class ConfigEditor(QDialog):
|
|||
txt = gui_hooks.addon_config_editor_will_save_json(txt)
|
||||
try:
|
||||
new_conf = json.loads(txt)
|
||||
jsonschema.validate(new_conf, self.parent().mgr._addon_schema(self.addon))
|
||||
jsonschema.validate(new_conf, self.mgr._addon_schema(self.addon))
|
||||
except ValidationError as e:
|
||||
# The user did edit the configuration and entered a value
|
||||
# which can not be interpreted.
|
||||
|
|
|
@ -35,11 +35,12 @@ from aqt.scheduling_ops import (
|
|||
suspend_cards,
|
||||
unsuspend_cards,
|
||||
)
|
||||
from aqt.sidebar import SidebarSearchBar, SidebarToolbar, SidebarTreeView
|
||||
from aqt.sidebar import SidebarTreeView
|
||||
from aqt.theme import theme_manager
|
||||
from aqt.utils import (
|
||||
TR,
|
||||
HelpPage,
|
||||
KeyboardModifiersPressed,
|
||||
askUser,
|
||||
current_top_level_widget,
|
||||
disable_help_button,
|
||||
|
@ -832,7 +833,9 @@ QTableView {{ gridline-color: {grid} }}
|
|||
gui_hooks.editor_did_init_left_buttons.remove(add_preview_button)
|
||||
|
||||
@ensure_editor_saved
|
||||
def onRowChanged(self, current: Optional[QItemSelection], previous: Optional[QItemSelection]) -> None:
|
||||
def onRowChanged(
|
||||
self, current: Optional[QItemSelection], previous: Optional[QItemSelection]
|
||||
) -> None:
|
||||
"""Update current note and hide/show editor."""
|
||||
if self._closeEventHasCleanedUp:
|
||||
return
|
||||
|
@ -975,15 +978,13 @@ QTableView {{ gridline-color: {grid} }}
|
|||
self.sidebar = SidebarTreeView(self)
|
||||
self.sidebarTree = self.sidebar # legacy alias
|
||||
dw.setWidget(self.sidebar)
|
||||
self.sidebar.toolbar = toolbar = SidebarToolbar(self.sidebar)
|
||||
self.sidebar.searchBar = searchBar = SidebarSearchBar(self.sidebar)
|
||||
qconnect(
|
||||
self.form.actionSidebarFilter.triggered,
|
||||
self.focusSidebarSearchBar,
|
||||
)
|
||||
grid = QGridLayout()
|
||||
grid.addWidget(searchBar, 0, 0)
|
||||
grid.addWidget(toolbar, 0, 1)
|
||||
grid.addWidget(self.sidebar.searchBar, 0, 0)
|
||||
grid.addWidget(self.sidebar.toolbar, 0, 1)
|
||||
grid.addWidget(self.sidebar, 1, 0, 1, 2)
|
||||
grid.setContentsMargins(0, 0, 0, 0)
|
||||
grid.setSpacing(0)
|
||||
|
@ -1116,10 +1117,7 @@ where id in %s"""
|
|||
|
||||
def createFilteredDeck(self) -> None:
|
||||
search = self.form.searchEdit.lineEdit().text()
|
||||
if (
|
||||
self.mw.col.schedVer() != 1
|
||||
and self.mw.app.keyboardModifiers() & Qt.AltModifier
|
||||
):
|
||||
if self.mw.col.schedVer() != 1 and KeyboardModifiersPressed().alt:
|
||||
aqt.dialogs.open("DynDeckConfDialog", self.mw, search_2=search)
|
||||
else:
|
||||
aqt.dialogs.open("DynDeckConfDialog", self.mw, search=search)
|
||||
|
@ -1482,9 +1480,9 @@ where id in %s"""
|
|||
|
||||
combo = "BrowserFindAndReplace"
|
||||
findhistory = restore_combo_history(frm.find, combo + "Find")
|
||||
frm.find.completer().setCaseSensitivity(True)
|
||||
frm.find._completer().setCaseSensitivity(True)
|
||||
replacehistory = restore_combo_history(frm.replace, combo + "Replace")
|
||||
frm.replace.completer().setCaseSensitivity(True)
|
||||
frm.replace._completer().setCaseSensitivity(True)
|
||||
|
||||
restore_is_checked(frm.re, combo + "Regex")
|
||||
restore_is_checked(frm.ignoreCase, combo + "ignoreCase")
|
||||
|
@ -1668,7 +1666,7 @@ where id in %s"""
|
|||
sm = self.form.tableView.selectionModel()
|
||||
idx = sm.currentIndex()
|
||||
self._moveCur(None, self.model.index(0, 0))
|
||||
if not self.mw.app.keyboardModifiers() & Qt.ShiftModifier:
|
||||
if not KeyboardModifiersPressed().shift:
|
||||
return
|
||||
idx2 = sm.currentIndex()
|
||||
item = QItemSelection(idx2, idx)
|
||||
|
@ -1678,7 +1676,7 @@ where id in %s"""
|
|||
sm = self.form.tableView.selectionModel()
|
||||
idx = sm.currentIndex()
|
||||
self._moveCur(None, self.model.index(len(self.model.cards) - 1, 0))
|
||||
if not self.mw.app.keyboardModifiers() & Qt.ShiftModifier:
|
||||
if not KeyboardModifiersPressed().shift:
|
||||
return
|
||||
idx2 = sm.currentIndex()
|
||||
item = QItemSelection(idx, idx2)
|
||||
|
@ -1728,6 +1726,9 @@ class ChangeModel(QDialog):
|
|||
restoreGeom(self, "changeModel")
|
||||
gui_hooks.state_did_reset.append(self.onReset)
|
||||
gui_hooks.current_note_type_did_change.append(self.on_note_type_change)
|
||||
# ugh - these are set dynamically by rebuildTemplateMap()
|
||||
self.tcombos: List[QComboBox] = []
|
||||
self.fcombos: List[QComboBox] = []
|
||||
self.exec_()
|
||||
|
||||
def on_note_type_change(self, notetype: NoteType) -> None:
|
||||
|
|
|
@ -795,7 +795,7 @@ class CardLayout(QDialog):
|
|||
showWarning(str(e))
|
||||
return
|
||||
self.mw.reset()
|
||||
tooltip(tr(TR.CARD_TEMPLATES_CHANGES_SAVED), parent=self.parent())
|
||||
tooltip(tr(TR.CARD_TEMPLATES_CHANGES_SAVED), parent=self.parentWidget())
|
||||
self.cleanup()
|
||||
gui_hooks.sidebar_should_refresh_notetypes()
|
||||
return QDialog.accept(self)
|
||||
|
|
|
@ -6,14 +6,14 @@ from __future__ import annotations
|
|||
from typing import Sequence
|
||||
|
||||
from anki.lang import TR
|
||||
from aqt import AnkiQt, QDialog
|
||||
from aqt import AnkiQt, QWidget
|
||||
from aqt.utils import tooltip, tr
|
||||
|
||||
|
||||
def remove_decks(
|
||||
*,
|
||||
mw: AnkiQt,
|
||||
parent: QDialog,
|
||||
parent: QWidget,
|
||||
deck_ids: Sequence[int],
|
||||
) -> None:
|
||||
mw.perform_op(
|
||||
|
|
|
@ -162,7 +162,6 @@ class DeckBrowser:
|
|||
],
|
||||
context=self,
|
||||
)
|
||||
self.web.key = "deckBrowser"
|
||||
self._drawButtons()
|
||||
if offset is not None:
|
||||
self._scrollToOffset(offset)
|
||||
|
|
|
@ -34,6 +34,7 @@ from aqt.theme import theme_manager
|
|||
from aqt.utils import (
|
||||
TR,
|
||||
HelpPage,
|
||||
KeyboardModifiersPressed,
|
||||
disable_help_button,
|
||||
getFile,
|
||||
openHelp,
|
||||
|
@ -753,7 +754,7 @@ class Editor:
|
|||
if m:
|
||||
highest = max(highest, sorted([int(x) for x in m])[-1])
|
||||
# reuse last?
|
||||
if not self.mw.app.keyboardModifiers() & Qt.AltModifier:
|
||||
if not KeyboardModifiersPressed().alt:
|
||||
highest += 1
|
||||
# must start at 1
|
||||
highest = max(1, highest)
|
||||
|
@ -1130,7 +1131,7 @@ class EditorWebView(AnkiWebView):
|
|||
strip_html = self.editor.mw.col.get_config_bool(
|
||||
Config.Bool.PASTE_STRIPS_FORMATTING
|
||||
)
|
||||
if self.editor.mw.app.queryKeyboardModifiers() & Qt.ShiftModifier:
|
||||
if KeyboardModifiersPressed().shift:
|
||||
strip_html = not strip_html
|
||||
return strip_html
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import html
|
|||
import re
|
||||
import sys
|
||||
import traceback
|
||||
from typing import Optional
|
||||
from typing import Optional, TextIO, cast
|
||||
|
||||
from markdown import markdown
|
||||
|
||||
|
@ -37,7 +37,7 @@ class ErrorHandler(QObject):
|
|||
qconnect(self.errorTimer, self._setTimer)
|
||||
self.pool = ""
|
||||
self._oldstderr = sys.stderr
|
||||
sys.stderr = self
|
||||
sys.stderr = cast(TextIO, self)
|
||||
|
||||
def unload(self) -> None:
|
||||
sys.stderr = self._oldstderr
|
||||
|
|
|
@ -26,7 +26,7 @@ from aqt.utils import (
|
|||
|
||||
class FieldDialog(QDialog):
|
||||
def __init__(
|
||||
self, mw: AnkiQt, nt: NoteType, parent: Optional[QDialog] = None
|
||||
self, mw: AnkiQt, nt: NoteType, parent: Optional[QWidget] = None
|
||||
) -> None:
|
||||
QDialog.__init__(self, parent or mw)
|
||||
self.mw = mw
|
||||
|
|
|
@ -72,6 +72,7 @@ from aqt.theme import theme_manager
|
|||
from aqt.utils import (
|
||||
TR,
|
||||
HelpPage,
|
||||
KeyboardModifiersPressed,
|
||||
askUser,
|
||||
checkInvalidFilename,
|
||||
current_top_level_widget,
|
||||
|
@ -121,7 +122,7 @@ class AnkiQt(QMainWindow):
|
|||
|
||||
def __init__(
|
||||
self,
|
||||
app: QApplication,
|
||||
app: aqt.AnkiApp,
|
||||
profileManager: ProfileManagerType,
|
||||
backend: _RustBackend,
|
||||
opts: Namespace,
|
||||
|
@ -138,9 +139,7 @@ class AnkiQt(QMainWindow):
|
|||
self.app = app
|
||||
self.pm = profileManager
|
||||
# init rest of app
|
||||
self.safeMode = (
|
||||
self.app.queryKeyboardModifiers() & Qt.ShiftModifier
|
||||
) or self.opts.safemode
|
||||
self.safeMode = (KeyboardModifiersPressed().shift) or self.opts.safemode
|
||||
try:
|
||||
self.setupUI()
|
||||
self.setupAddons(args)
|
||||
|
@ -927,10 +926,8 @@ title="%s" %s>%s</button>""" % (
|
|||
|
||||
# force webengine processes to load before cwd is changed
|
||||
if isWin:
|
||||
for o in self.web, self.bottomWeb:
|
||||
o.requiresCol = False
|
||||
o._domReady = False
|
||||
o._page.setContent(bytes("", "ascii"))
|
||||
for webview in self.web, self.bottomWeb:
|
||||
webview.force_load_hack()
|
||||
|
||||
def closeAllWindows(self, onsuccess: Callable) -> None:
|
||||
aqt.dialogs.closeAll(onsuccess)
|
||||
|
@ -1103,8 +1100,7 @@ title="%s" %s>%s</button>""" % (
|
|||
("y", self.on_sync_button_clicked),
|
||||
]
|
||||
self.applyShortcuts(globalShortcuts)
|
||||
|
||||
self.stateShortcuts: Sequence[Tuple[str, Callable]] = []
|
||||
self.stateShortcuts: List[QShortcut] = []
|
||||
|
||||
def applyShortcuts(
|
||||
self, shortcuts: Sequence[Tuple[str, Callable]]
|
||||
|
@ -1281,7 +1277,7 @@ title="%s" %s>%s</button>""" % (
|
|||
deck = self._selectedDeck()
|
||||
if not deck:
|
||||
return
|
||||
want_old = self.app.queryKeyboardModifiers() & Qt.ShiftModifier
|
||||
want_old = KeyboardModifiersPressed().shift
|
||||
if want_old:
|
||||
aqt.dialogs.open("DeckStats", self)
|
||||
else:
|
||||
|
@ -1538,13 +1534,14 @@ title="%s" %s>%s</button>""" % (
|
|||
frm = self.debug_diag_form = aqt.forms.debug.Ui_Dialog()
|
||||
|
||||
class DebugDialog(QDialog):
|
||||
silentlyClose = True
|
||||
|
||||
def reject(self) -> None:
|
||||
super().reject()
|
||||
saveSplitter(frm.splitter, "DebugConsoleWindow")
|
||||
saveGeom(self, "DebugConsoleWindow")
|
||||
|
||||
d = self.debugDiag = DebugDialog()
|
||||
d.silentlyClose = True
|
||||
disable_help_button(d)
|
||||
frm.setupUi(d)
|
||||
restoreGeom(d, "DebugConsoleWindow")
|
||||
|
@ -1708,7 +1705,8 @@ title="%s" %s>%s</button>""" % (
|
|||
if not self.hideMenuAccels:
|
||||
return
|
||||
tgt = tgt or self
|
||||
for action in tgt.findChildren(QAction):
|
||||
for action_ in tgt.findChildren(QAction):
|
||||
action = cast(QAction, action_)
|
||||
txt = str(action.text())
|
||||
m = re.match(r"^(.+)\(&.+\)(.+)?", txt)
|
||||
if m:
|
||||
|
@ -1716,7 +1714,7 @@ title="%s" %s>%s</button>""" % (
|
|||
|
||||
def hideStatusTips(self) -> None:
|
||||
for action in self.findChildren(QAction):
|
||||
action.setStatusTip("")
|
||||
cast(QAction, action).setStatusTip("")
|
||||
|
||||
def onMacMinimize(self) -> None:
|
||||
self.setWindowState(self.windowState() | Qt.WindowMinimized) # type: ignore
|
||||
|
|
|
@ -31,7 +31,7 @@ class Models(QDialog):
|
|||
def __init__(
|
||||
self,
|
||||
mw: AnkiQt,
|
||||
parent: Optional[QDialog] = None,
|
||||
parent: Optional[QWidget] = None,
|
||||
fromMain: bool = False,
|
||||
selected_notetype_id: Optional[int] = None,
|
||||
):
|
||||
|
|
|
@ -7,9 +7,8 @@ from typing import Callable, Optional, Sequence
|
|||
|
||||
from anki.lang import TR
|
||||
from anki.notes import Note
|
||||
from aqt import AnkiQt
|
||||
from aqt import AnkiQt, QWidget
|
||||
from aqt.main import PerformOpOptionalSuccessCallback
|
||||
from aqt.qt import QDialog
|
||||
from aqt.utils import show_invalid_search_error, showInfo, tr
|
||||
|
||||
|
||||
|
@ -52,7 +51,7 @@ def remove_tags(
|
|||
def find_and_replace(
|
||||
*,
|
||||
mw: AnkiQt,
|
||||
parent: QDialog,
|
||||
parent: QWidget,
|
||||
note_ids: Sequence[int],
|
||||
search: str,
|
||||
replacement: str,
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
# Copyright: Ankitects Pty Ltd and contributors
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
# mypy: check-untyped-defs
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
import time
|
||||
from typing import Any, Callable, Optional, Tuple, Union
|
||||
|
||||
import aqt.browser
|
||||
from anki.cards import Card
|
||||
from anki.collection import Config
|
||||
from aqt import AnkiQt, gui_hooks
|
||||
|
@ -300,6 +303,12 @@ class MultiCardPreviewer(Previewer):
|
|||
|
||||
class BrowserPreviewer(MultiCardPreviewer):
|
||||
_last_card_id = 0
|
||||
_parent: Optional[aqt.browser.Browser]
|
||||
|
||||
def __init__(
|
||||
self, parent: aqt.browser.Browser, mw: AnkiQt, on_close: Callable[[], None]
|
||||
) -> None:
|
||||
super().__init__(parent=parent, mw=mw, on_close=on_close)
|
||||
|
||||
def card(self) -> Optional[Card]:
|
||||
if self._parent.singleCard:
|
||||
|
|
|
@ -16,7 +16,7 @@ from aqt.utils import TR, disable_help_button, tr
|
|||
class ProgressManager:
|
||||
def __init__(self, mw: aqt.AnkiQt) -> None:
|
||||
self.mw = mw
|
||||
self.app = QApplication.instance()
|
||||
self.app = mw.app
|
||||
self.inDB = False
|
||||
self.blockUpdates = False
|
||||
self._show_timer: Optional[QTimer] = None
|
||||
|
@ -75,7 +75,7 @@ class ProgressManager:
|
|||
max: int = 0,
|
||||
min: int = 0,
|
||||
label: Optional[str] = None,
|
||||
parent: Optional[QDialog] = None,
|
||||
parent: Optional[QWidget] = None,
|
||||
immediate: bool = False,
|
||||
) -> Optional[ProgressDialog]:
|
||||
self._levels += 1
|
||||
|
|
|
@ -17,7 +17,7 @@ from aqt.utils import getText, tooltip, tr
|
|||
def set_due_date_dialog(
|
||||
*,
|
||||
mw: aqt.AnkiQt,
|
||||
parent: QDialog,
|
||||
parent: QWidget,
|
||||
card_ids: List[int],
|
||||
config_key: Optional[Config.String.Key.V],
|
||||
) -> None:
|
||||
|
@ -51,7 +51,7 @@ def set_due_date_dialog(
|
|||
)
|
||||
|
||||
|
||||
def forget_cards(*, mw: aqt.AnkiQt, parent: QDialog, card_ids: List[int]) -> None:
|
||||
def forget_cards(*, mw: aqt.AnkiQt, parent: QWidget, card_ids: List[int]) -> None:
|
||||
if not card_ids:
|
||||
return
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ from aqt.qt import *
|
|||
from aqt.theme import ColoredIcon, theme_manager
|
||||
from aqt.utils import (
|
||||
TR,
|
||||
KeyboardModifiersPressed,
|
||||
askUser,
|
||||
getOnlyText,
|
||||
show_invalid_search_error,
|
||||
|
@ -254,9 +255,7 @@ class SidebarModel(QAbstractItemModel):
|
|||
return QVariant(item.tooltip)
|
||||
return QVariant(theme_manager.icon_from_resources(item.icon))
|
||||
|
||||
def setData(
|
||||
self, index: QModelIndex, text: QVariant, _role: int = Qt.EditRole
|
||||
) -> bool:
|
||||
def setData(self, index: QModelIndex, text: str, _role: int = Qt.EditRole) -> bool:
|
||||
return self.sidebar._on_rename(index.internalPointer(), text)
|
||||
|
||||
def supportedDropActions(self) -> Qt.DropActions:
|
||||
|
@ -354,6 +353,10 @@ def _want_right_border() -> bool:
|
|||
return not isMac or theme_manager.night_mode
|
||||
|
||||
|
||||
# fixme: we should have a top-level Sidebar class inheriting from QWidget that
|
||||
# handles the treeview, search bar and so on. Currently the treeview embeds the
|
||||
# search bar which is wrong, and the layout code is handled in browser.py instead
|
||||
# of here
|
||||
class SidebarTreeView(QTreeView):
|
||||
def __init__(self, browser: aqt.browser.Browser) -> None:
|
||||
super().__init__()
|
||||
|
@ -390,6 +393,10 @@ class SidebarTreeView(QTreeView):
|
|||
|
||||
self.setStyleSheet("QTreeView { %s }" % ";".join(styles))
|
||||
|
||||
# these do not really belong here, they should be in a higher-level class
|
||||
self.toolbar = SidebarToolbar(self)
|
||||
self.searchBar = SidebarSearchBar(self)
|
||||
|
||||
@property
|
||||
def tool(self) -> SidebarTool:
|
||||
return self._tool
|
||||
|
@ -410,7 +417,7 @@ class SidebarTreeView(QTreeView):
|
|||
self.setExpandsOnDoubleClick(double_click_expands)
|
||||
|
||||
def model(self) -> SidebarModel:
|
||||
return super().model()
|
||||
return cast(SidebarModel, super().model())
|
||||
|
||||
# Refreshing
|
||||
###########################
|
||||
|
@ -512,22 +519,22 @@ class SidebarTreeView(QTreeView):
|
|||
joiner: SearchJoiner = "AND",
|
||||
) -> None:
|
||||
"""Modify the current search string based on modifier keys, then refresh."""
|
||||
mods = self.mw.app.keyboardModifiers()
|
||||
mods = KeyboardModifiersPressed()
|
||||
previous = SearchNode(parsable_text=self.browser.current_search())
|
||||
current = self.mw.col.group_searches(*terms, joiner=joiner)
|
||||
|
||||
# if Alt pressed, invert
|
||||
if mods & Qt.AltModifier:
|
||||
if mods.alt:
|
||||
current = SearchNode(negated=current)
|
||||
|
||||
try:
|
||||
if mods & Qt.ControlModifier and mods & Qt.ShiftModifier:
|
||||
if mods.control and mods.shift:
|
||||
# If Ctrl+Shift, replace searches nodes of the same type.
|
||||
search = self.col.replace_in_search_node(previous, current)
|
||||
elif mods & Qt.ControlModifier:
|
||||
elif mods.control:
|
||||
# If Ctrl, AND with previous
|
||||
search = self.col.join_searches(previous, current, "AND")
|
||||
elif mods & Qt.ShiftModifier:
|
||||
elif mods.shift:
|
||||
# If Shift, OR with previous
|
||||
search = self.col.join_searches(previous, current, "OR")
|
||||
else:
|
||||
|
|
|
@ -15,7 +15,7 @@ import wave
|
|||
from abc import ABC, abstractmethod
|
||||
from concurrent.futures import Future
|
||||
from operator import itemgetter
|
||||
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple
|
||||
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, cast
|
||||
|
||||
import aqt
|
||||
from anki import hooks
|
||||
|
@ -568,7 +568,7 @@ class QtAudioInputRecorder(Recorder):
|
|||
super().start(on_done)
|
||||
|
||||
def _on_read_ready(self) -> None:
|
||||
self._buffer += self._iodevice.readAll()
|
||||
self._buffer += cast(bytes, self._iodevice.readAll())
|
||||
|
||||
def stop(self, on_done: Callable[[str], None]) -> None:
|
||||
def on_stop_timer() -> None:
|
||||
|
|
|
@ -33,9 +33,9 @@ class StudyDeck(QDialog):
|
|||
help: HelpPageArgument = HelpPage.KEYBOARD_SHORTCUTS,
|
||||
current: Optional[str] = None,
|
||||
cancel: bool = True,
|
||||
parent: Optional[QDialog] = None,
|
||||
parent: Optional[QWidget] = None,
|
||||
dyn: bool = False,
|
||||
buttons: Optional[List[str]] = None,
|
||||
buttons: Optional[List[Union[str, QPushButton]]] = None,
|
||||
geomKey: str = "default",
|
||||
) -> None:
|
||||
QDialog.__init__(self, parent or mw)
|
||||
|
@ -53,8 +53,10 @@ class StudyDeck(QDialog):
|
|||
self.form.buttonBox.button(QDialogButtonBox.Cancel)
|
||||
)
|
||||
if buttons is not None:
|
||||
for b in buttons:
|
||||
self.form.buttonBox.addButton(b, QDialogButtonBox.ActionRole)
|
||||
for button_or_label in buttons:
|
||||
self.form.buttonBox.addButton(
|
||||
button_or_label, QDialogButtonBox.ActionRole
|
||||
)
|
||||
else:
|
||||
b = QPushButton(tr(TR.ACTIONS_ADD))
|
||||
b.setShortcut(QKeySequence("Ctrl+N"))
|
||||
|
@ -89,7 +91,7 @@ class StudyDeck(QDialog):
|
|||
self.exec_()
|
||||
|
||||
def eventFilter(self, obj: QObject, evt: QEvent) -> bool:
|
||||
if evt.type() == QEvent.KeyPress:
|
||||
if isinstance(evt, QKeyEvent) and evt.type() == QEvent.KeyPress:
|
||||
new_row = current_row = self.form.list.currentRow()
|
||||
rows_count = self.form.list.count()
|
||||
key = evt.key()
|
||||
|
@ -98,7 +100,10 @@ class StudyDeck(QDialog):
|
|||
new_row = current_row - 1
|
||||
elif key == Qt.Key_Down:
|
||||
new_row = current_row + 1
|
||||
elif evt.modifiers() & Qt.ControlModifier and Qt.Key_1 <= key <= Qt.Key_9:
|
||||
elif (
|
||||
int(evt.modifiers()) & Qt.ControlModifier
|
||||
and Qt.Key_1 <= key <= Qt.Key_9
|
||||
):
|
||||
row_index = key - Qt.Key_1
|
||||
if row_index < rows_count:
|
||||
new_row = row_index
|
||||
|
|
|
@ -12,24 +12,24 @@ from aqt.qt import *
|
|||
|
||||
|
||||
class TagEdit(QLineEdit):
|
||||
completer: Union[QCompleter, TagCompleter]
|
||||
_completer: Union[QCompleter, TagCompleter]
|
||||
|
||||
lostFocus = pyqtSignal()
|
||||
|
||||
# 0 = tags, 1 = decks
|
||||
def __init__(self, parent: QDialog, type: int = 0) -> None:
|
||||
def __init__(self, parent: QWidget, type: int = 0) -> None:
|
||||
QLineEdit.__init__(self, parent)
|
||||
self.col: Optional[Collection] = None
|
||||
self.model = QStringListModel()
|
||||
self.type = type
|
||||
if type == 0:
|
||||
self.completer = TagCompleter(self.model, parent, self)
|
||||
self._completer = TagCompleter(self.model, parent, self)
|
||||
else:
|
||||
self.completer = QCompleter(self.model, parent)
|
||||
self.completer.setCompletionMode(QCompleter.PopupCompletion)
|
||||
self.completer.setCaseSensitivity(Qt.CaseInsensitive)
|
||||
self.completer.setFilterMode(Qt.MatchContains)
|
||||
self.setCompleter(self.completer)
|
||||
self._completer = QCompleter(self.model, parent)
|
||||
self._completer.setCompletionMode(QCompleter.PopupCompletion)
|
||||
self._completer.setCaseSensitivity(Qt.CaseInsensitive)
|
||||
self._completer.setFilterMode(Qt.MatchContains)
|
||||
self.setCompleter(self._completer)
|
||||
|
||||
def setCol(self, col: Collection) -> None:
|
||||
"Set the current col, updating list of available tags."
|
||||
|
@ -47,29 +47,29 @@ class TagEdit(QLineEdit):
|
|||
def keyPressEvent(self, evt: QKeyEvent) -> None:
|
||||
if evt.key() in (Qt.Key_Up, Qt.Key_Down):
|
||||
# show completer on arrow key up/down
|
||||
if not self.completer.popup().isVisible():
|
||||
if not self._completer.popup().isVisible():
|
||||
self.showCompleter()
|
||||
return
|
||||
if evt.key() == Qt.Key_Tab and evt.modifiers() & Qt.ControlModifier:
|
||||
if evt.key() == Qt.Key_Tab and int(evt.modifiers()) & Qt.ControlModifier:
|
||||
# select next completion
|
||||
if not self.completer.popup().isVisible():
|
||||
if not self._completer.popup().isVisible():
|
||||
self.showCompleter()
|
||||
index = self.completer.currentIndex()
|
||||
self.completer.popup().setCurrentIndex(index)
|
||||
index = self._completer.currentIndex()
|
||||
self._completer.popup().setCurrentIndex(index)
|
||||
cur_row = index.row()
|
||||
if not self.completer.setCurrentRow(cur_row + 1):
|
||||
self.completer.setCurrentRow(0)
|
||||
if not self._completer.setCurrentRow(cur_row + 1):
|
||||
self._completer.setCurrentRow(0)
|
||||
return
|
||||
if (
|
||||
evt.key() in (Qt.Key_Enter, Qt.Key_Return)
|
||||
and self.completer.popup().isVisible()
|
||||
and self._completer.popup().isVisible()
|
||||
):
|
||||
# apply first completion if no suggestion selected
|
||||
selected_row = self.completer.popup().currentIndex().row()
|
||||
selected_row = self._completer.popup().currentIndex().row()
|
||||
if selected_row == -1:
|
||||
self.completer.setCurrentRow(0)
|
||||
index = self.completer.currentIndex()
|
||||
self.completer.popup().setCurrentIndex(index)
|
||||
self._completer.setCurrentRow(0)
|
||||
index = self._completer.currentIndex()
|
||||
self._completer.popup().setCurrentIndex(index)
|
||||
self.hideCompleter()
|
||||
QWidget.keyPressEvent(self, evt)
|
||||
return
|
||||
|
@ -90,18 +90,18 @@ class TagEdit(QLineEdit):
|
|||
gui_hooks.tag_editor_did_process_key(self, evt)
|
||||
|
||||
def showCompleter(self) -> None:
|
||||
self.completer.setCompletionPrefix(self.text())
|
||||
self.completer.complete()
|
||||
self._completer.setCompletionPrefix(self.text())
|
||||
self._completer.complete()
|
||||
|
||||
def focusOutEvent(self, evt: QFocusEvent) -> None:
|
||||
QLineEdit.focusOutEvent(self, evt)
|
||||
self.lostFocus.emit() # type: ignore
|
||||
self.completer.popup().hide()
|
||||
self._completer.popup().hide()
|
||||
|
||||
def hideCompleter(self) -> None:
|
||||
if sip.isdeleted(self.completer):
|
||||
if sip.isdeleted(self._completer):
|
||||
return
|
||||
self.completer.popup().hide()
|
||||
self._completer.popup().hide()
|
||||
|
||||
|
||||
class TagCompleter(QCompleter):
|
||||
|
|
|
@ -15,8 +15,8 @@ class TagLimit(QDialog):
|
|||
self.tags: str = ""
|
||||
self.tags_list: List[str] = []
|
||||
self.mw = mw
|
||||
self.parent: Optional[QWidget] = parent
|
||||
self.deck = self.parent.deck
|
||||
self.parent_: Optional[CustomStudy] = parent
|
||||
self.deck = self.parent_.deck
|
||||
self.dialog = aqt.forms.taglimit.Ui_Dialog()
|
||||
self.dialog.setupUi(self)
|
||||
disable_help_button(self)
|
||||
|
|
|
@ -86,12 +86,12 @@ class ThemeManager:
|
|||
else:
|
||||
# specified colours
|
||||
icon = QIcon(path.path)
|
||||
img = icon.pixmap(16)
|
||||
painter = QPainter(img)
|
||||
pixmap = icon.pixmap(16)
|
||||
painter = QPainter(pixmap)
|
||||
painter.setCompositionMode(QPainter.CompositionMode_SourceIn)
|
||||
painter.fillRect(img.rect(), QColor(path.current_color(self.night_mode)))
|
||||
painter.fillRect(pixmap.rect(), QColor(path.current_color(self.night_mode)))
|
||||
painter.end()
|
||||
icon = QIcon(img)
|
||||
icon = QIcon(pixmap)
|
||||
return icon
|
||||
|
||||
return cache.setdefault(path, icon)
|
||||
|
|
|
@ -111,7 +111,7 @@ def openHelp(section: HelpPageArgument) -> None:
|
|||
openLink(link)
|
||||
|
||||
|
||||
def openLink(link: str) -> None:
|
||||
def openLink(link: Union[str, QUrl]) -> None:
|
||||
tooltip(tr(TR.QT_MISC_LOADING), period=1000)
|
||||
with noBundledLibs():
|
||||
QDesktopServices.openUrl(QUrl(link))
|
||||
|
@ -119,7 +119,7 @@ def openLink(link: str) -> None:
|
|||
|
||||
def showWarning(
|
||||
text: str,
|
||||
parent: Optional[QDialog] = None,
|
||||
parent: Optional[QWidget] = None,
|
||||
help: HelpPageArgument = "",
|
||||
title: str = "Anki",
|
||||
textFormat: Optional[TextFormat] = None,
|
||||
|
@ -139,7 +139,7 @@ def showCritical(
|
|||
return showInfo(text, parent, help, "critical", title=title, textFormat=textFormat)
|
||||
|
||||
|
||||
def show_invalid_search_error(err: Exception, parent: Optional[QDialog] = None) -> None:
|
||||
def show_invalid_search_error(err: Exception, parent: Optional[QWidget] = None) -> None:
|
||||
"Render search errors in markdown, then display a warning."
|
||||
text = str(err)
|
||||
if isinstance(err, InvalidInput):
|
||||
|
@ -149,7 +149,7 @@ def show_invalid_search_error(err: Exception, parent: Optional[QDialog] = None)
|
|||
|
||||
def showInfo(
|
||||
text: str,
|
||||
parent: Union[Literal[False], QDialog] = False,
|
||||
parent: Optional[QWidget] = None,
|
||||
help: HelpPageArgument = "",
|
||||
type: str = "info",
|
||||
title: str = "Anki",
|
||||
|
@ -158,7 +158,7 @@ def showInfo(
|
|||
) -> int:
|
||||
"Show a small info window with an OK button."
|
||||
parent_widget: QWidget
|
||||
if parent is False:
|
||||
if parent is None:
|
||||
parent_widget = aqt.mw.app.activeWindow() or aqt.mw
|
||||
else:
|
||||
parent_widget = parent
|
||||
|
@ -214,6 +214,7 @@ def showText(
|
|||
disable_help_button(diag)
|
||||
layout = QVBoxLayout(diag)
|
||||
diag.setLayout(layout)
|
||||
text: Union[QPlainTextEdit, QTextBrowser]
|
||||
if plain_text_edit:
|
||||
# used by the importer
|
||||
text = QPlainTextEdit()
|
||||
|
@ -222,10 +223,10 @@ def showText(
|
|||
else:
|
||||
text = QTextBrowser()
|
||||
text.setOpenExternalLinks(True)
|
||||
if type == "text":
|
||||
text.setPlainText(txt)
|
||||
else:
|
||||
text.setHtml(txt)
|
||||
if type == "text":
|
||||
text.setPlainText(txt)
|
||||
else:
|
||||
text.setHtml(txt)
|
||||
layout.addWidget(text)
|
||||
box = QDialogButtonBox(QDialogButtonBox.Close)
|
||||
layout.addWidget(box)
|
||||
|
@ -263,7 +264,7 @@ def showText(
|
|||
|
||||
def askUser(
|
||||
text: str,
|
||||
parent: QDialog = None,
|
||||
parent: QWidget = None,
|
||||
help: HelpPageArgument = None,
|
||||
defaultno: bool = False,
|
||||
msgfunc: Optional[Callable] = None,
|
||||
|
@ -296,7 +297,7 @@ class ButtonedDialog(QMessageBox):
|
|||
self,
|
||||
text: str,
|
||||
buttons: List[str],
|
||||
parent: Optional[QDialog] = None,
|
||||
parent: Optional[QWidget] = None,
|
||||
help: HelpPageArgument = None,
|
||||
title: str = "Anki",
|
||||
):
|
||||
|
@ -329,7 +330,7 @@ class ButtonedDialog(QMessageBox):
|
|||
def askUserDialog(
|
||||
text: str,
|
||||
buttons: List[str],
|
||||
parent: Optional[QDialog] = None,
|
||||
parent: Optional[QWidget] = None,
|
||||
help: HelpPageArgument = None,
|
||||
title: str = "Anki",
|
||||
) -> ButtonedDialog:
|
||||
|
@ -342,7 +343,7 @@ def askUserDialog(
|
|||
class GetTextDialog(QDialog):
|
||||
def __init__(
|
||||
self,
|
||||
parent: Optional[QDialog],
|
||||
parent: Optional[QWidget],
|
||||
question: str,
|
||||
help: HelpPageArgument = None,
|
||||
edit: Optional[QLineEdit] = None,
|
||||
|
@ -389,7 +390,7 @@ class GetTextDialog(QDialog):
|
|||
|
||||
def getText(
|
||||
prompt: str,
|
||||
parent: Optional[QDialog] = None,
|
||||
parent: Optional[QWidget] = None,
|
||||
help: HelpPageArgument = None,
|
||||
edit: Optional[QLineEdit] = None,
|
||||
default: str = "",
|
||||
|
@ -446,7 +447,7 @@ def chooseList(
|
|||
|
||||
|
||||
def getTag(
|
||||
parent: QDialog, deck: Collection, question: str, **kwargs: Any
|
||||
parent: QWidget, deck: Collection, question: str, **kwargs: Any
|
||||
) -> Tuple[str, int]:
|
||||
from aqt.tagedit import TagEdit
|
||||
|
||||
|
@ -459,7 +460,8 @@ def getTag(
|
|||
|
||||
def disable_help_button(widget: QWidget) -> None:
|
||||
"Disable the help button in the window titlebar."
|
||||
flags = cast(Qt.WindowType, widget.windowFlags() & ~Qt.WindowContextHelpButtonHint)
|
||||
flags_int = int(widget.windowFlags()) & ~Qt.WindowContextHelpButtonHint
|
||||
flags = Qt.WindowFlags(flags_int) # type: ignore
|
||||
widget.setWindowFlags(flags)
|
||||
|
||||
|
||||
|
@ -468,7 +470,7 @@ def disable_help_button(widget: QWidget) -> None:
|
|||
|
||||
|
||||
def getFile(
|
||||
parent: QDialog,
|
||||
parent: QWidget,
|
||||
title: str,
|
||||
# single file returned unless multi=True
|
||||
cb: Optional[Callable[[Union[str, Sequence[str]]], None]],
|
||||
|
@ -548,9 +550,9 @@ def getSaveFile(
|
|||
return file
|
||||
|
||||
|
||||
def saveGeom(widget: QDialog, key: str) -> None:
|
||||
def saveGeom(widget: QWidget, key: str) -> None:
|
||||
key += "Geom"
|
||||
if isMac and widget.windowState() & Qt.WindowFullScreen:
|
||||
if isMac and int(widget.windowState()) & Qt.WindowFullScreen:
|
||||
geom = None
|
||||
else:
|
||||
geom = widget.saveGeometry()
|
||||
|
@ -600,12 +602,12 @@ def ensureWidgetInScreenBoundaries(widget: QWidget) -> None:
|
|||
widget.move(x, y)
|
||||
|
||||
|
||||
def saveState(widget: QFileDialog, key: str) -> None:
|
||||
def saveState(widget: Union[QFileDialog, QMainWindow], key: str) -> None:
|
||||
key += "State"
|
||||
aqt.mw.pm.profile[key] = widget.saveState()
|
||||
|
||||
|
||||
def restoreState(widget: Union[aqt.AnkiQt, QFileDialog], key: str) -> None:
|
||||
def restoreState(widget: Union[QFileDialog, QMainWindow], key: str) -> None:
|
||||
key += "State"
|
||||
if aqt.mw.pm.profile.get(key):
|
||||
widget.restoreState(aqt.mw.pm.profile[key])
|
||||
|
@ -633,12 +635,12 @@ def restoreHeader(widget: QHeaderView, key: str) -> None:
|
|||
widget.restoreState(aqt.mw.pm.profile[key])
|
||||
|
||||
|
||||
def save_is_checked(widget: QWidget, key: str) -> None:
|
||||
def save_is_checked(widget: QCheckBox, key: str) -> None:
|
||||
key += "IsChecked"
|
||||
aqt.mw.pm.profile[key] = widget.isChecked()
|
||||
|
||||
|
||||
def restore_is_checked(widget: QWidget, key: str) -> None:
|
||||
def restore_is_checked(widget: QCheckBox, key: str) -> None:
|
||||
key += "IsChecked"
|
||||
if aqt.mw.pm.profile.get(key) is not None:
|
||||
widget.setChecked(aqt.mw.pm.profile[key])
|
||||
|
@ -719,8 +721,9 @@ def maybeHideClose(bbox: QDialogButtonBox) -> None:
|
|||
def addCloseShortcut(widg: QDialog) -> None:
|
||||
if not isMac:
|
||||
return
|
||||
widg._closeShortcut = QShortcut(QKeySequence("Ctrl+W"), widg)
|
||||
qconnect(widg._closeShortcut.activated, widg.reject)
|
||||
shortcut = QShortcut(QKeySequence("Ctrl+W"), widg)
|
||||
qconnect(shortcut.activated, widg.reject)
|
||||
setattr(widg, "_closeShortcut", shortcut)
|
||||
|
||||
|
||||
def downArrow() -> str:
|
||||
|
@ -732,7 +735,7 @@ def downArrow() -> str:
|
|||
|
||||
def top_level_widget(widget: QWidget) -> QWidget:
|
||||
window = None
|
||||
while widget := widget.parent():
|
||||
while widget := widget.parentWidget():
|
||||
window = widget
|
||||
return window
|
||||
|
||||
|
@ -754,7 +757,7 @@ _tooltipLabel: Optional[QLabel] = None
|
|||
def tooltip(
|
||||
msg: str,
|
||||
period: int = 3000,
|
||||
parent: Optional[aqt.AnkiQt] = None,
|
||||
parent: Optional[QWidget] = None,
|
||||
x_offset: int = 0,
|
||||
y_offset: int = 100,
|
||||
) -> None:
|
||||
|
@ -1015,3 +1018,24 @@ def ensure_editor_saved_on_trigger(func: Callable) -> Callable:
|
|||
into functions connected to a `triggered` signal.
|
||||
"""
|
||||
return pyqtSlot()(ensure_editor_saved(func)) # type: ignore
|
||||
|
||||
|
||||
class KeyboardModifiersPressed:
|
||||
"Util for type-safe checks of currently-pressed modifier keys."
|
||||
|
||||
def __init__(self) -> None:
|
||||
from aqt import mw
|
||||
|
||||
self._modifiers = int(mw.app.keyboardModifiers())
|
||||
|
||||
@property
|
||||
def shift(self) -> bool:
|
||||
return bool(self._modifiers & Qt.ShiftModifier)
|
||||
|
||||
@property
|
||||
def control(self) -> bool:
|
||||
return bool(self._modifiers & Qt.ControlModifier)
|
||||
|
||||
@property
|
||||
def alt(self) -> bool:
|
||||
return bool(self._modifiers & Qt.AltModifier)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# Copyright: Ankitects Pty Ltd and contributors
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
import dataclasses
|
||||
import json
|
||||
import re
|
||||
|
@ -31,12 +32,15 @@ class AnkiWebPage(QWebEnginePage):
|
|||
|
||||
def _setupBridge(self) -> None:
|
||||
class Bridge(QObject):
|
||||
def __init__(self, bridge_handler: Callable[[str], Any]) -> None:
|
||||
super().__init__()
|
||||
self.onCmd = bridge_handler
|
||||
|
||||
@pyqtSlot(str, result=str) # type: ignore
|
||||
def cmd(self, str: str) -> Any:
|
||||
return json.dumps(self.onCmd(str))
|
||||
|
||||
self._bridge = Bridge()
|
||||
self._bridge.onCmd = self._onCmd
|
||||
self._bridge = Bridge(self._onCmd)
|
||||
|
||||
self._channel = QWebChannel(self)
|
||||
self._channel.registerObject("py", self._bridge)
|
||||
|
@ -46,7 +50,7 @@ class AnkiWebPage(QWebEnginePage):
|
|||
jsfile = QFile(qwebchannel)
|
||||
if not jsfile.open(QIODevice.ReadOnly):
|
||||
print(f"Error opening '{qwebchannel}': {jsfile.error()}", file=sys.stderr)
|
||||
jstext = bytes(jsfile.readAll()).decode("utf-8")
|
||||
jstext = bytes(cast(bytes, jsfile.readAll())).decode("utf-8")
|
||||
jsfile.close()
|
||||
|
||||
script = QWebEngineScript()
|
||||
|
@ -131,7 +135,7 @@ class AnkiWebPage(QWebEnginePage):
|
|||
openLink(url)
|
||||
return False
|
||||
|
||||
def _onCmd(self, str: str) -> None:
|
||||
def _onCmd(self, str: str) -> Any:
|
||||
return self._onBridgeCmd(str)
|
||||
|
||||
def javaScriptAlert(self, url: QUrl, text: str) -> None:
|
||||
|
@ -252,7 +256,7 @@ class AnkiWebView(QWebEngineView):
|
|||
# disable pinch to zoom gesture
|
||||
if isinstance(evt, QNativeGestureEvent):
|
||||
return True
|
||||
elif evt.type() == QEvent.MouseButtonRelease:
|
||||
elif isinstance(evt, QMouseEvent) and evt.type() == QEvent.MouseButtonRelease:
|
||||
if evt.button() == Qt.MidButton and isLin:
|
||||
self.onMiddleClickPaste()
|
||||
return True
|
||||
|
@ -273,7 +277,9 @@ class AnkiWebView(QWebEngineView):
|
|||
w.close()
|
||||
else:
|
||||
# in the main window, removes focus from type in area
|
||||
self.parent().setFocus()
|
||||
parent = self.parent()
|
||||
assert isinstance(parent, QWidget)
|
||||
parent.setFocus()
|
||||
break
|
||||
w = w.parent()
|
||||
|
||||
|
@ -315,15 +321,16 @@ class AnkiWebView(QWebEngineView):
|
|||
self.set_open_links_externally(True)
|
||||
|
||||
def _setHtml(self, html: str) -> None:
|
||||
app = QApplication.instance()
|
||||
oldFocus = app.focusWidget()
|
||||
from aqt import mw
|
||||
|
||||
oldFocus = mw.app.focusWidget()
|
||||
self._domDone = False
|
||||
self._page.setHtml(html)
|
||||
# work around webengine stealing focus on setHtml()
|
||||
if oldFocus:
|
||||
oldFocus.setFocus()
|
||||
|
||||
def load(self, url: QUrl) -> None:
|
||||
def load_url(self, url: QUrl) -> None:
|
||||
# allow queuing actions when loading url directly
|
||||
self._domDone = False
|
||||
super().load(url)
|
||||
|
@ -641,5 +648,12 @@ document.head.appendChild(style);
|
|||
else:
|
||||
extra = ""
|
||||
self.hide_while_preserving_layout()
|
||||
self.load(QUrl(f"{mw.serverURL()}_anki/pages/{name}.html{extra}"))
|
||||
self.load_url(QUrl(f"{mw.serverURL()}_anki/pages/{name}.html{extra}"))
|
||||
self.inject_dynamic_style_and_show()
|
||||
|
||||
def force_load_hack(self) -> None:
|
||||
"""Force process to initialize.
|
||||
Must be done on Windows prior to changing current working directory."""
|
||||
self.requiresCol = False
|
||||
self._domReady = False
|
||||
self._page.setContent(bytes("", "ascii"))
|
||||
|
|
Loading…
Reference in a new issue