mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
add qconnect helper and some type hints
The type hints allow mypy to check the gui_hook calls, revealing a bunch of places that are broken as they expect no arguments like the legacy hooks. To make mypy happy about PyQt's signal.connect(func), a qconnect() helper has been added.
This commit is contained in:
parent
c6d0425020
commit
8310cb7a0e
14 changed files with 83 additions and 74 deletions
|
@ -1,7 +1,7 @@
|
||||||
# Copyright: Ankitects Pty Ltd and contributors
|
# Copyright: Ankitects Pty Ltd and contributors
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
from typing import Callable, List
|
from typing import Callable, List, Optional
|
||||||
|
|
||||||
import aqt.deckchooser
|
import aqt.deckchooser
|
||||||
import aqt.editor
|
import aqt.editor
|
||||||
|
@ -143,7 +143,7 @@ class AddCards(QDialog):
|
||||||
self.history = self.history[:15]
|
self.history = self.history[:15]
|
||||||
self.historyButton.setEnabled(True)
|
self.historyButton.setEnabled(True)
|
||||||
|
|
||||||
def onHistory(self):
|
def onHistory(self) -> None:
|
||||||
m = QMenu(self)
|
m = QMenu(self)
|
||||||
for nid in self.history:
|
for nid in self.history:
|
||||||
if self.mw.col.findNotes("nid:%s" % nid):
|
if self.mw.col.findNotes("nid:%s" % nid):
|
||||||
|
@ -152,7 +152,7 @@ class AddCards(QDialog):
|
||||||
if len(txt) > 30:
|
if len(txt) > 30:
|
||||||
txt = txt[:30] + "..."
|
txt = txt[:30] + "..."
|
||||||
a = m.addAction(_('Edit "%s"') % txt)
|
a = m.addAction(_('Edit "%s"') % txt)
|
||||||
a.triggered.connect(lambda b, nid=nid: self.editHistory(nid))
|
qconnect(a.triggered, lambda b, nid=nid: self.editHistory(nid))
|
||||||
else:
|
else:
|
||||||
a = m.addAction(_("(Note deleted)"))
|
a = m.addAction(_("(Note deleted)"))
|
||||||
a.setEnabled(False)
|
a.setEnabled(False)
|
||||||
|
@ -164,12 +164,12 @@ class AddCards(QDialog):
|
||||||
browser.form.searchEdit.lineEdit().setText("nid:%d" % nid)
|
browser.form.searchEdit.lineEdit().setText("nid:%d" % nid)
|
||||||
browser.onSearchActivated()
|
browser.onSearchActivated()
|
||||||
|
|
||||||
def addNote(self, note):
|
def addNote(self, note) -> Optional[Note]:
|
||||||
note.model()["did"] = self.deckChooser.selectedId()
|
note.model()["did"] = self.deckChooser.selectedId()
|
||||||
ret = note.dupeOrEmpty()
|
ret = note.dupeOrEmpty()
|
||||||
if ret == 1:
|
if ret == 1:
|
||||||
showWarning(_("The first field is empty."), help="AddItems#AddError")
|
showWarning(_("The first field is empty."), help="AddItems#AddError")
|
||||||
return
|
return None
|
||||||
if "{{cloze:" in note.model()["tmpls"][0]["qfmt"]:
|
if "{{cloze:" in note.model()["tmpls"][0]["qfmt"]:
|
||||||
if not self.mw.col.models._availClozeOrds(
|
if not self.mw.col.models._availClozeOrds(
|
||||||
note.model(), note.joinedFields(), False
|
note.model(), note.joinedFields(), False
|
||||||
|
@ -180,7 +180,7 @@ class AddCards(QDialog):
|
||||||
"but have not made any cloze deletions. Proceed?"
|
"but have not made any cloze deletions. Proceed?"
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
return
|
return None
|
||||||
cards = self.mw.col.addNote(note)
|
cards = self.mw.col.addNote(note)
|
||||||
if not cards:
|
if not cards:
|
||||||
showWarning(
|
showWarning(
|
||||||
|
@ -191,7 +191,7 @@ question on all cards."""
|
||||||
),
|
),
|
||||||
help="AddItems",
|
help="AddItems",
|
||||||
)
|
)
|
||||||
return
|
return None
|
||||||
self.mw.col.clearUndo()
|
self.mw.col.clearUndo()
|
||||||
self.addHistory(note)
|
self.addHistory(note)
|
||||||
self.mw.requireReset()
|
self.mw.requireReset()
|
||||||
|
|
|
@ -9,11 +9,12 @@ import sre_constants
|
||||||
import time
|
import time
|
||||||
import unicodedata
|
import unicodedata
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
from typing import Callable, List, Optional
|
from typing import Callable, List, Optional, Union
|
||||||
|
|
||||||
import anki
|
import anki
|
||||||
import aqt.forms
|
import aqt.forms
|
||||||
from anki import hooks
|
from anki import hooks
|
||||||
|
from anki.cards import Card
|
||||||
from anki.collection import _Collection
|
from anki.collection import _Collection
|
||||||
from anki.consts import *
|
from anki.consts import *
|
||||||
from anki.lang import _, ngettext
|
from anki.lang import _, ngettext
|
||||||
|
@ -27,6 +28,7 @@ from anki.utils import (
|
||||||
isWin,
|
isWin,
|
||||||
)
|
)
|
||||||
from aqt import AnkiQt, gui_hooks
|
from aqt import AnkiQt, gui_hooks
|
||||||
|
from aqt.editor import Editor
|
||||||
from aqt.qt import *
|
from aqt.qt import *
|
||||||
from aqt.sound import allSounds, clearAudioQueue, play
|
from aqt.sound import allSounds, clearAudioQueue, play
|
||||||
from aqt.utils import (
|
from aqt.utils import (
|
||||||
|
@ -556,8 +558,9 @@ class Browser(QMainWindow):
|
||||||
model: DataModel
|
model: DataModel
|
||||||
mw: AnkiQt
|
mw: AnkiQt
|
||||||
col: _Collection
|
col: _Collection
|
||||||
|
editor: Optional[Editor]
|
||||||
|
|
||||||
def __init__(self, mw: AnkiQt):
|
def __init__(self, mw: AnkiQt) -> None:
|
||||||
QMainWindow.__init__(self, None, Qt.Window)
|
QMainWindow.__init__(self, None, Qt.Window)
|
||||||
self.mw = mw
|
self.mw = mw
|
||||||
self.col = self.mw.col
|
self.col = self.mw.col
|
||||||
|
@ -572,7 +575,7 @@ class Browser(QMainWindow):
|
||||||
restoreState(self, "editor")
|
restoreState(self, "editor")
|
||||||
restoreSplitter(self.form.splitter, "editor3")
|
restoreSplitter(self.form.splitter, "editor3")
|
||||||
self.form.splitter.setChildrenCollapsible(False)
|
self.form.splitter.setChildrenCollapsible(False)
|
||||||
self.card = None
|
self.card: Optional[Card] = None
|
||||||
self.setupColumns()
|
self.setupColumns()
|
||||||
self.setupTable()
|
self.setupTable()
|
||||||
self.setupMenus()
|
self.setupMenus()
|
||||||
|
@ -584,7 +587,7 @@ class Browser(QMainWindow):
|
||||||
self.setupSearch()
|
self.setupSearch()
|
||||||
self.show()
|
self.show()
|
||||||
|
|
||||||
def setupMenus(self):
|
def setupMenus(self) -> None:
|
||||||
# pylint: disable=unnecessary-lambda
|
# pylint: disable=unnecessary-lambda
|
||||||
# actions
|
# actions
|
||||||
f = self.form
|
f = self.form
|
||||||
|
@ -635,9 +638,9 @@ class Browser(QMainWindow):
|
||||||
f.actionGuide.triggered.connect(self.onHelp)
|
f.actionGuide.triggered.connect(self.onHelp)
|
||||||
# keyboard shortcut for shift+home/end
|
# keyboard shortcut for shift+home/end
|
||||||
self.pgUpCut = QShortcut(QKeySequence("Shift+Home"), self)
|
self.pgUpCut = QShortcut(QKeySequence("Shift+Home"), self)
|
||||||
self.pgUpCut.activated.connect(self.onFirstCard)
|
qconnect(self.pgUpCut.activated, self.onFirstCard)
|
||||||
self.pgDownCut = QShortcut(QKeySequence("Shift+End"), self)
|
self.pgDownCut = QShortcut(QKeySequence("Shift+End"), self)
|
||||||
self.pgDownCut.activated.connect(self.onLastCard)
|
qconnect(self.pgDownCut.activated, self.onLastCard)
|
||||||
# add-on hook
|
# add-on hook
|
||||||
gui_hooks.browser_menus_did_init(self)
|
gui_hooks.browser_menus_did_init(self)
|
||||||
self.mw.maybeHideAccelerators(self)
|
self.mw.maybeHideAccelerators(self)
|
||||||
|
@ -646,14 +649,14 @@ class Browser(QMainWindow):
|
||||||
self.form.tableView.setContextMenuPolicy(Qt.CustomContextMenu)
|
self.form.tableView.setContextMenuPolicy(Qt.CustomContextMenu)
|
||||||
self.form.tableView.customContextMenuRequested.connect(self.onContextMenu)
|
self.form.tableView.customContextMenuRequested.connect(self.onContextMenu)
|
||||||
|
|
||||||
def onContextMenu(self, _point):
|
def onContextMenu(self, _point) -> None:
|
||||||
m = QMenu()
|
m = QMenu()
|
||||||
for act in self.form.menu_Cards.actions():
|
for act in self.form.menu_Cards.actions():
|
||||||
m.addAction(act)
|
m.addAction(act)
|
||||||
m.addSeparator()
|
m.addSeparator()
|
||||||
for act in self.form.menu_Notes.actions():
|
for act in self.form.menu_Notes.actions():
|
||||||
m.addAction(act)
|
m.addAction(act)
|
||||||
gui_hooks.browser_will_show_context_menu(self, m)
|
gui_hooks.browser_will_show_context_menu(self)
|
||||||
qtMenuShortcutWorkaround(m)
|
qtMenuShortcutWorkaround(m)
|
||||||
m.exec_(QCursor.pos())
|
m.exec_(QCursor.pos())
|
||||||
|
|
||||||
|
@ -771,7 +774,7 @@ class Browser(QMainWindow):
|
||||||
self.search()
|
self.search()
|
||||||
|
|
||||||
# search triggered programmatically. caller must have saved note first.
|
# search triggered programmatically. caller must have saved note first.
|
||||||
def search(self):
|
def search(self) -> None:
|
||||||
if "is:current" in self._lastSearchTxt:
|
if "is:current" in self._lastSearchTxt:
|
||||||
# show current card if there is one
|
# show current card if there is one
|
||||||
c = self.mw.reviewer.card
|
c = self.mw.reviewer.card
|
||||||
|
@ -827,7 +830,7 @@ class Browser(QMainWindow):
|
||||||
"Update current note and hide/show editor."
|
"Update current note and hide/show editor."
|
||||||
self.editor.saveNow(lambda: self._onRowChanged(current, previous))
|
self.editor.saveNow(lambda: self._onRowChanged(current, previous))
|
||||||
|
|
||||||
def _onRowChanged(self, current, previous):
|
def _onRowChanged(self, current, previous) -> None:
|
||||||
update = self.updateTitle()
|
update = self.updateTitle()
|
||||||
show = self.model.cards and update == 1
|
show = self.model.cards and update == 1
|
||||||
self.form.splitter.widget(1).setVisible(not not show)
|
self.form.splitter.widget(1).setVisible(not not show)
|
||||||
|
@ -841,7 +844,7 @@ class Browser(QMainWindow):
|
||||||
else:
|
else:
|
||||||
self.editor.setNote(self.card.note(reload=True), focusTo=self.focusTo)
|
self.editor.setNote(self.card.note(reload=True), focusTo=self.focusTo)
|
||||||
self.focusTo = None
|
self.focusTo = None
|
||||||
self.editor.card = self.card
|
self.editor.card = self.card # type: ignore
|
||||||
self.singleCard = True
|
self.singleCard = True
|
||||||
self._updateFlagsMenu()
|
self._updateFlagsMenu()
|
||||||
gui_hooks.browser_did_change_row(self)
|
gui_hooks.browser_did_change_row(self)
|
||||||
|
@ -1530,7 +1533,7 @@ where id in %s"""
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
_previewTimer = None
|
_previewTimer = None
|
||||||
_lastPreviewRender = 0
|
_lastPreviewRender: Union[int,float] = 0
|
||||||
_lastPreviewState = None
|
_lastPreviewState = None
|
||||||
_previewCardChanged = False
|
_previewCardChanged = False
|
||||||
|
|
||||||
|
@ -1669,7 +1672,7 @@ where id in %s"""
|
||||||
self._previewTimer.stop()
|
self._previewTimer.stop()
|
||||||
self._previewTimer = None
|
self._previewTimer = None
|
||||||
|
|
||||||
def _renderScheduledPreview(self):
|
def _renderScheduledPreview(self) -> None:
|
||||||
self._cancelPreviewTimer()
|
self._cancelPreviewTimer()
|
||||||
self._lastPreviewRender = time.time()
|
self._lastPreviewRender = time.time()
|
||||||
|
|
||||||
|
@ -2019,7 +2022,7 @@ update cards set usn=?, mod=?, did=? where id in """
|
||||||
# Edit: undo
|
# Edit: undo
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def setupHooks(self):
|
def setupHooks(self) -> None:
|
||||||
gui_hooks.undo_state_did_change.append(self.onUndoState)
|
gui_hooks.undo_state_did_change.append(self.onUndoState)
|
||||||
gui_hooks.state_did_reset.append(self.onReset)
|
gui_hooks.state_did_reset.append(self.onReset)
|
||||||
gui_hooks.editor_did_fire_typing_timer.append(self.refreshCurrentCard)
|
gui_hooks.editor_did_fire_typing_timer.append(self.refreshCurrentCard)
|
||||||
|
@ -2029,7 +2032,7 @@ update cards set usn=?, mod=?, did=? where id in """
|
||||||
hooks.note_type_added.append(self.maybeRefreshSidebar)
|
hooks.note_type_added.append(self.maybeRefreshSidebar)
|
||||||
hooks.deck_added.append(self.maybeRefreshSidebar)
|
hooks.deck_added.append(self.maybeRefreshSidebar)
|
||||||
|
|
||||||
def teardownHooks(self):
|
def teardownHooks(self) -> None:
|
||||||
gui_hooks.undo_state_did_change.remove(self.onUndoState)
|
gui_hooks.undo_state_did_change.remove(self.onUndoState)
|
||||||
gui_hooks.state_did_reset.remove(self.onReset)
|
gui_hooks.state_did_reset.remove(self.onReset)
|
||||||
gui_hooks.editor_did_fire_typing_timer.remove(self.refreshCurrentCard)
|
gui_hooks.editor_did_fire_typing_timer.remove(self.refreshCurrentCard)
|
||||||
|
@ -2261,7 +2264,7 @@ update cards set usn=?, mod=?, did=? where id in """
|
||||||
|
|
||||||
|
|
||||||
class ChangeModel(QDialog):
|
class ChangeModel(QDialog):
|
||||||
def __init__(self, browser, nids):
|
def __init__(self, browser, nids) -> None:
|
||||||
QDialog.__init__(self, browser)
|
QDialog.__init__(self, browser)
|
||||||
self.browser = browser
|
self.browser = browser
|
||||||
self.nids = nids
|
self.nids = nids
|
||||||
|
@ -2394,7 +2397,7 @@ class ChangeModel(QDialog):
|
||||||
old=self.oldModel["flds"], combos=self.fcombos, new=self.targetModel["flds"]
|
old=self.oldModel["flds"], combos=self.fcombos, new=self.targetModel["flds"]
|
||||||
)
|
)
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self) -> None:
|
||||||
gui_hooks.state_did_reset.remove(self.onReset)
|
gui_hooks.state_did_reset.remove(self.onReset)
|
||||||
gui_hooks.current_note_type_did_change.remove(self.onReset)
|
gui_hooks.current_note_type_did_change.remove(self.onReset)
|
||||||
self.modelChooser.cleanup()
|
self.modelChooser.cleanup()
|
||||||
|
|
|
@ -326,7 +326,7 @@ Please create a new card type first."""
|
||||||
self._previewTimer.stop()
|
self._previewTimer.stop()
|
||||||
self._previewTimer = None
|
self._previewTimer = None
|
||||||
|
|
||||||
def _renderPreview(self):
|
def _renderPreview(self) -> None:
|
||||||
self.cancelPreviewTimer()
|
self.cancelPreviewTimer()
|
||||||
|
|
||||||
c = self.card
|
c = self.card
|
||||||
|
|
|
@ -235,16 +235,16 @@ where id > ?""",
|
||||||
# Options
|
# Options
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def _showOptions(self, did):
|
def _showOptions(self, did) -> None:
|
||||||
m = QMenu(self.mw)
|
m = QMenu(self.mw)
|
||||||
a = m.addAction(_("Rename"))
|
a = m.addAction(_("Rename"))
|
||||||
a.triggered.connect(lambda b, did=did: self._rename(did))
|
qconnect(a.triggered, lambda b, did=did: self._rename(did))
|
||||||
a = m.addAction(_("Options"))
|
a = m.addAction(_("Options"))
|
||||||
a.triggered.connect(lambda b, did=did: self._options(did))
|
qconnect(a.triggered, lambda b, did=did: self._options(did))
|
||||||
a = m.addAction(_("Export"))
|
a = m.addAction(_("Export"))
|
||||||
a.triggered.connect(lambda b, did=did: self._export(did))
|
qconnect(a.triggered, lambda b, did=did: self._export(did))
|
||||||
a = m.addAction(_("Delete"))
|
a = m.addAction(_("Delete"))
|
||||||
a.triggered.connect(lambda b, did=did: self._delete(did))
|
qconnect(a.triggered, lambda b, did=did: self._delete(did))
|
||||||
gui_hooks.deck_browser_will_show_options_menu(m, did)
|
gui_hooks.deck_browser_will_show_options_menu(m, did)
|
||||||
m.exec_(QCursor.pos())
|
m.exec_(QCursor.pos())
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,9 @@ from aqt.utils import shortcut
|
||||||
|
|
||||||
|
|
||||||
class DeckChooser(QHBoxLayout):
|
class DeckChooser(QHBoxLayout):
|
||||||
def __init__(self, mw, widget, label=True, start=None):
|
def __init__(self, mw, widget: QWidget, label=True, start=None) -> None:
|
||||||
QHBoxLayout.__init__(self)
|
QHBoxLayout.__init__(self)
|
||||||
self.widget = widget
|
self.widget = widget # type: ignore
|
||||||
self.mw = mw
|
self.mw = mw
|
||||||
self.deck = mw.col
|
self.deck = mw.col
|
||||||
self.label = label
|
self.label = label
|
||||||
|
@ -63,7 +63,7 @@ class DeckChooser(QHBoxLayout):
|
||||||
def hide(self):
|
def hide(self):
|
||||||
self.widget.hide()
|
self.widget.hide()
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self) -> None:
|
||||||
gui_hooks.current_note_type_did_change.remove(self.onModelChange)
|
gui_hooks.current_note_type_did_change.remove(self.onModelChange)
|
||||||
|
|
||||||
def onModelChange(self):
|
def onModelChange(self):
|
||||||
|
|
|
@ -10,7 +10,7 @@ from aqt.utils import restoreGeom, saveGeom, tooltip
|
||||||
|
|
||||||
|
|
||||||
class EditCurrent(QDialog):
|
class EditCurrent(QDialog):
|
||||||
def __init__(self, mw):
|
def __init__(self, mw) -> None:
|
||||||
QDialog.__init__(self, None, Qt.Window)
|
QDialog.__init__(self, None, Qt.Window)
|
||||||
mw.setupDialogGC(self)
|
mw.setupDialogGC(self)
|
||||||
self.mw = mw
|
self.mw = mw
|
||||||
|
@ -33,7 +33,7 @@ class EditCurrent(QDialog):
|
||||||
# pylint: disable=unnecessary-lambda
|
# pylint: disable=unnecessary-lambda
|
||||||
self.mw.progress.timer(100, lambda: self.editor.web.setFocus(), False)
|
self.mw.progress.timer(100, lambda: self.editor.web.setFocus(), False)
|
||||||
|
|
||||||
def onReset(self):
|
def onReset(self) -> None:
|
||||||
# lazy approach for now: throw away edits
|
# lazy approach for now: throw away edits
|
||||||
try:
|
try:
|
||||||
n = self.editor.note
|
n = self.editor.note
|
||||||
|
@ -58,7 +58,7 @@ class EditCurrent(QDialog):
|
||||||
def saveAndClose(self):
|
def saveAndClose(self):
|
||||||
self.editor.saveNow(self._saveAndClose)
|
self.editor.saveNow(self._saveAndClose)
|
||||||
|
|
||||||
def _saveAndClose(self):
|
def _saveAndClose(self) -> None:
|
||||||
gui_hooks.state_did_reset.remove(self.onReset)
|
gui_hooks.state_did_reset.remove(self.onReset)
|
||||||
r = self.mw.reviewer
|
r = self.mw.reviewer
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -21,6 +21,7 @@ import aqt
|
||||||
import aqt.sound
|
import aqt.sound
|
||||||
from anki.hooks import runFilter
|
from anki.hooks import runFilter
|
||||||
from anki.lang import _
|
from anki.lang import _
|
||||||
|
from anki.notes import Note
|
||||||
from anki.sync import AnkiRequestsClient
|
from anki.sync import AnkiRequestsClient
|
||||||
from anki.utils import checksum, isWin, namedtmp, stripHTMLMedia
|
from anki.utils import checksum, isWin, namedtmp, stripHTMLMedia
|
||||||
from aqt import AnkiQt, gui_hooks
|
from aqt import AnkiQt, gui_hooks
|
||||||
|
@ -67,13 +68,13 @@ html { background: %s; }
|
||||||
|
|
||||||
# caller is responsible for resetting note on reset
|
# caller is responsible for resetting note on reset
|
||||||
class Editor:
|
class Editor:
|
||||||
def __init__(self, mw: AnkiQt, widget, parentWindow, addMode=False):
|
def __init__(self, mw: AnkiQt, widget, parentWindow, addMode=False) -> None:
|
||||||
self.mw = mw
|
self.mw = mw
|
||||||
self.widget = widget
|
self.widget = widget
|
||||||
self.parentWindow = parentWindow
|
self.parentWindow = parentWindow
|
||||||
self.note = None
|
self.note: Optional[Note] = None
|
||||||
self.addMode = addMode
|
self.addMode = addMode
|
||||||
self.currentField = None
|
self.currentField: Optional[int] = None
|
||||||
# current card, for card layout
|
# current card, for card layout
|
||||||
self.card = None
|
self.card = None
|
||||||
self.setupOuter()
|
self.setupOuter()
|
||||||
|
@ -91,7 +92,7 @@ class Editor:
|
||||||
self.widget.setLayout(l)
|
self.widget.setLayout(l)
|
||||||
self.outerLayout = l
|
self.outerLayout = l
|
||||||
|
|
||||||
def setupWeb(self):
|
def setupWeb(self) -> None:
|
||||||
self.web = EditorWebView(self.widget, self)
|
self.web = EditorWebView(self.widget, self)
|
||||||
self.web.title = "editor"
|
self.web.title = "editor"
|
||||||
self.web.allowDrops = True
|
self.web.allowDrops = True
|
||||||
|
@ -159,7 +160,7 @@ class Editor:
|
||||||
fldsTitle=_("Customize Fields"),
|
fldsTitle=_("Customize Fields"),
|
||||||
cardsTitle=shortcut(_("Customize Card Templates (Ctrl+L)")),
|
cardsTitle=shortcut(_("Customize Card Templates (Ctrl+L)")),
|
||||||
)
|
)
|
||||||
bgcol = self.mw.app.palette().window().color().name()
|
bgcol = self.mw.app.palette().window().color().name() # type: ignore
|
||||||
# then load page
|
# then load page
|
||||||
self.web.stdHtml(
|
self.web.stdHtml(
|
||||||
_html % (bgcol, bgcol, topbuts, _("Show Duplicates")),
|
_html % (bgcol, bgcol, topbuts, _("Show Duplicates")),
|
||||||
|
@ -260,7 +261,7 @@ class Editor:
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def setupShortcuts(self):
|
def setupShortcuts(self) -> None:
|
||||||
# if a third element is provided, enable shortcut even when no field selected
|
# if a third element is provided, enable shortcut even when no field selected
|
||||||
cuts: List[Tuple] = [
|
cuts: List[Tuple] = [
|
||||||
("Ctrl+L", self.onCardLayout, True),
|
("Ctrl+L", self.onCardLayout, True),
|
||||||
|
@ -292,7 +293,7 @@ class Editor:
|
||||||
fn = self._addFocusCheck(fn)
|
fn = self._addFocusCheck(fn)
|
||||||
else:
|
else:
|
||||||
keys, fn, _ = row
|
keys, fn, _ = row
|
||||||
QShortcut(QKeySequence(keys), self.widget, activated=fn)
|
QShortcut(QKeySequence(keys), self.widget, activated=fn) # type: ignore
|
||||||
|
|
||||||
def _addFocusCheck(self, fn):
|
def _addFocusCheck(self, fn):
|
||||||
def checkFocus():
|
def checkFocus():
|
||||||
|
@ -329,7 +330,7 @@ class Editor:
|
||||||
# JS->Python bridge
|
# JS->Python bridge
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def onBridgeCmd(self, cmd):
|
def onBridgeCmd(self, cmd) -> None:
|
||||||
if not self.note:
|
if not self.note:
|
||||||
# shutdown
|
# shutdown
|
||||||
return
|
return
|
||||||
|
@ -399,7 +400,7 @@ class Editor:
|
||||||
def loadNoteKeepingFocus(self):
|
def loadNoteKeepingFocus(self):
|
||||||
self.loadNote(self.currentField)
|
self.loadNote(self.currentField)
|
||||||
|
|
||||||
def loadNote(self, focusTo=None):
|
def loadNote(self, focusTo=None) -> None:
|
||||||
if not self.note:
|
if not self.note:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -426,7 +427,7 @@ class Editor:
|
||||||
)
|
)
|
||||||
self.web.evalWithCallback(js, oncallback)
|
self.web.evalWithCallback(js, oncallback)
|
||||||
|
|
||||||
def fonts(self):
|
def fonts(self) -> List[Tuple[str,int,bool]]:
|
||||||
return [
|
return [
|
||||||
(gui_hooks.editor_will_use_font_for_field(f["font"]), f["size"], f["rtl"])
|
(gui_hooks.editor_will_use_font_for_field(f["font"]), f["size"], f["rtl"])
|
||||||
for f in self.note.model()["flds"]
|
for f in self.note.model()["flds"]
|
||||||
|
@ -528,7 +529,7 @@ class Editor:
|
||||||
if not self.tags.text() or not self.addMode:
|
if not self.tags.text() or not self.addMode:
|
||||||
self.tags.setText(self.note.stringTags().strip())
|
self.tags.setText(self.note.stringTags().strip())
|
||||||
|
|
||||||
def saveTags(self):
|
def saveTags(self) -> None:
|
||||||
if not self.note:
|
if not self.note:
|
||||||
return
|
return
|
||||||
tagsTxt = unicodedata.normalize("NFC", self.tags.text())
|
tagsTxt = unicodedata.normalize("NFC", self.tags.text())
|
||||||
|
@ -1103,14 +1104,14 @@ class EditorWebView(AnkiWebView):
|
||||||
mime.setHtml("<!--anki-->" + html)
|
mime.setHtml("<!--anki-->" + html)
|
||||||
clip.setMimeData(mime)
|
clip.setMimeData(mime)
|
||||||
|
|
||||||
def contextMenuEvent(self, evt):
|
def contextMenuEvent(self, evt) -> None:
|
||||||
m = QMenu(self)
|
m = QMenu(self)
|
||||||
a = m.addAction(_("Cut"))
|
a = m.addAction(_("Cut"))
|
||||||
a.triggered.connect(self.onCut)
|
qconnect(a.triggered, self.onCut)
|
||||||
a = m.addAction(_("Copy"))
|
a = m.addAction(_("Copy"))
|
||||||
a.triggered.connect(self.onCopy)
|
qconnect(a.triggered, self.onCopy)
|
||||||
a = m.addAction(_("Paste"))
|
a = m.addAction(_("Paste"))
|
||||||
a.triggered.connect(self.onPaste)
|
qconnect(a.triggered, self.onPaste)
|
||||||
gui_hooks.editor_will_show_context_menu(self, m)
|
gui_hooks.editor_will_show_context_menu(self, m)
|
||||||
m.popup(QCursor.pos())
|
m.popup(QCursor.pos())
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ class ChangeMap(QDialog):
|
||||||
|
|
||||||
|
|
||||||
class ImportDialog(QDialog):
|
class ImportDialog(QDialog):
|
||||||
def __init__(self, mw: AnkiQt, importer):
|
def __init__(self, mw: AnkiQt, importer) -> None:
|
||||||
QDialog.__init__(self, mw, Qt.Window)
|
QDialog.__init__(self, mw, Qt.Window)
|
||||||
self.mw = mw
|
self.mw = mw
|
||||||
self.importer = importer
|
self.importer = importer
|
||||||
|
@ -278,7 +278,7 @@ you can enter it here. Use \\t to represent tab."""
|
||||||
else:
|
else:
|
||||||
self.showMapping(keepMapping=True)
|
self.showMapping(keepMapping=True)
|
||||||
|
|
||||||
def reject(self):
|
def reject(self) -> None:
|
||||||
self.modelChooser.cleanup()
|
self.modelChooser.cleanup()
|
||||||
self.deck.cleanup()
|
self.deck.cleanup()
|
||||||
gui_hooks.current_note_type_did_change.remove(self.modelChanged)
|
gui_hooks.current_note_type_did_change.remove(self.modelChanged)
|
||||||
|
|
|
@ -569,7 +569,7 @@ from the profile screen."
|
||||||
def _deckBrowserState(self, oldState: str) -> None:
|
def _deckBrowserState(self, oldState: str) -> None:
|
||||||
self.deckBrowser.show()
|
self.deckBrowser.show()
|
||||||
|
|
||||||
def _colLoadingState(self, oldState):
|
def _colLoadingState(self, oldState) -> None:
|
||||||
"Run once, when col is loaded."
|
"Run once, when col is loaded."
|
||||||
self.enableColMenuItems()
|
self.enableColMenuItems()
|
||||||
# ensure cwd is set if media dir exists
|
# ensure cwd is set if media dir exists
|
||||||
|
@ -918,7 +918,7 @@ QTreeWidget {
|
||||||
# Undo & autosave
|
# Undo & autosave
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def onUndo(self):
|
def onUndo(self) -> None:
|
||||||
n = self.col.undoName()
|
n = self.col.undoName()
|
||||||
if not n:
|
if not n:
|
||||||
return
|
return
|
||||||
|
|
|
@ -9,9 +9,9 @@ from aqt.utils import shortcut
|
||||||
|
|
||||||
|
|
||||||
class ModelChooser(QHBoxLayout):
|
class ModelChooser(QHBoxLayout):
|
||||||
def __init__(self, mw, widget, label=True):
|
def __init__(self, mw, widget, label=True) -> None:
|
||||||
QHBoxLayout.__init__(self)
|
QHBoxLayout.__init__(self)
|
||||||
self.widget = widget
|
self.widget = widget # type: ignore
|
||||||
self.mw = mw
|
self.mw = mw
|
||||||
self.deck = mw.col
|
self.deck = mw.col
|
||||||
self.label = label
|
self.label = label
|
||||||
|
@ -19,7 +19,7 @@ class ModelChooser(QHBoxLayout):
|
||||||
self.setSpacing(8)
|
self.setSpacing(8)
|
||||||
self.setupModels()
|
self.setupModels()
|
||||||
gui_hooks.state_did_reset.append(self.onReset)
|
gui_hooks.state_did_reset.append(self.onReset)
|
||||||
self.widget.setLayout(self)
|
self.widget.setLayout(self) # type: ignore
|
||||||
|
|
||||||
def setupModels(self):
|
def setupModels(self):
|
||||||
if self.label:
|
if self.label:
|
||||||
|
@ -40,7 +40,7 @@ class ModelChooser(QHBoxLayout):
|
||||||
self.models.setSizePolicy(sizePolicy)
|
self.models.setSizePolicy(sizePolicy)
|
||||||
self.updateModels()
|
self.updateModels()
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self) -> None:
|
||||||
gui_hooks.state_did_reset.remove(self.onReset)
|
gui_hooks.state_did_reset.remove(self.onReset)
|
||||||
|
|
||||||
def onReset(self):
|
def onReset(self):
|
||||||
|
@ -57,12 +57,12 @@ class ModelChooser(QHBoxLayout):
|
||||||
|
|
||||||
aqt.models.Models(self.mw, self.widget)
|
aqt.models.Models(self.mw, self.widget)
|
||||||
|
|
||||||
def onModelChange(self):
|
def onModelChange(self) -> None:
|
||||||
from aqt.studydeck import StudyDeck
|
from aqt.studydeck import StudyDeck
|
||||||
|
|
||||||
current = self.deck.models.current()["name"]
|
current = self.deck.models.current()["name"]
|
||||||
# edit button
|
# edit button
|
||||||
edit = QPushButton(_("Manage"), clicked=self.onEdit)
|
edit = QPushButton(_("Manage"), clicked=self.onEdit) # type: ignore
|
||||||
|
|
||||||
def nameFunc():
|
def nameFunc():
|
||||||
return sorted(self.deck.models.allNames())
|
return sorted(self.deck.models.allNames())
|
||||||
|
|
|
@ -14,6 +14,7 @@ from PyQt5.QtCore import pyqtRemoveInputHook # pylint: disable=no-name-in-modul
|
||||||
from PyQt5.QtGui import * # type: ignore
|
from PyQt5.QtGui import * # type: ignore
|
||||||
from PyQt5.QtWebEngineWidgets import * # type: ignore
|
from PyQt5.QtWebEngineWidgets import * # type: ignore
|
||||||
from PyQt5.QtWidgets import *
|
from PyQt5.QtWidgets import *
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
from anki.utils import isMac, isWin
|
from anki.utils import isMac, isWin
|
||||||
|
|
||||||
|
@ -52,3 +53,7 @@ qtpoint = QT_VERSION & 0xFF
|
||||||
|
|
||||||
if qtmajor != 5 or qtminor < 9 or qtminor == 10:
|
if qtmajor != 5 or qtminor < 9 or qtminor == 10:
|
||||||
raise Exception("Anki does not support your Qt version.")
|
raise Exception("Anki does not support your Qt version.")
|
||||||
|
|
||||||
|
def qconnect(signal: Callable, func: Callable) -> None:
|
||||||
|
"Helper to work around type checking not working with signal.connect(func)."
|
||||||
|
signal.connect(func) # type: ignore
|
|
@ -8,7 +8,7 @@ import html.parser
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
import unicodedata as ucd
|
import unicodedata as ucd
|
||||||
from typing import List
|
from typing import List, Optional
|
||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
from anki import hooks
|
from anki import hooks
|
||||||
|
@ -33,13 +33,13 @@ class Reviewer:
|
||||||
def __init__(self, mw: AnkiQt) -> None:
|
def __init__(self, mw: AnkiQt) -> None:
|
||||||
self.mw = mw
|
self.mw = mw
|
||||||
self.web = mw.web
|
self.web = mw.web
|
||||||
self.card = None
|
self.card: Optional[Card] = None
|
||||||
self.cardQueue: List[Card] = []
|
self.cardQueue: List[Card] = []
|
||||||
self.hadCardQueue = False
|
self.hadCardQueue = False
|
||||||
self._answeredIds: List[int] = []
|
self._answeredIds: List[int] = []
|
||||||
self._recordedAudio = None
|
self._recordedAudio = None
|
||||||
self.typeCorrect = None # web init happens before this is set
|
self.typeCorrect = None # web init happens before this is set
|
||||||
self.state = None
|
self.state: Optional[str] = None
|
||||||
self.bottom = aqt.toolbar.BottomBar(mw, mw.bottomWeb)
|
self.bottom = aqt.toolbar.BottomBar(mw, mw.bottomWeb)
|
||||||
hooks.card_did_leech.append(self.onLeech)
|
hooks.card_did_leech.append(self.onLeech)
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ class Reviewer:
|
||||||
# id was deleted
|
# id was deleted
|
||||||
return
|
return
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self) -> None:
|
||||||
gui_hooks.reviewer_will_end()
|
gui_hooks.reviewer_will_end()
|
||||||
|
|
||||||
# Fetching a card
|
# Fetching a card
|
||||||
|
@ -170,7 +170,7 @@ class Reviewer:
|
||||||
def _mungeQA(self, buf):
|
def _mungeQA(self, buf):
|
||||||
return self.typeAnsFilter(mungeQA(self.mw.col, buf))
|
return self.typeAnsFilter(mungeQA(self.mw.col, buf))
|
||||||
|
|
||||||
def _showQuestion(self):
|
def _showQuestion(self) -> None:
|
||||||
self._reps += 1
|
self._reps += 1
|
||||||
self.state = "question"
|
self.state = "question"
|
||||||
self.typedAnswer = None
|
self.typedAnswer = None
|
||||||
|
@ -217,7 +217,7 @@ The front of this card is empty. Please run Tools>Empty Cards."""
|
||||||
# Showing the answer
|
# Showing the answer
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def _showAnswer(self):
|
def _showAnswer(self) -> None:
|
||||||
if self.mw.state != "review":
|
if self.mw.state != "review":
|
||||||
# showing resetRequired screen; ignore space
|
# showing resetRequired screen; ignore space
|
||||||
return
|
return
|
||||||
|
@ -689,7 +689,7 @@ time = %(time)d;
|
||||||
]
|
]
|
||||||
return opts
|
return opts
|
||||||
|
|
||||||
def showContextMenu(self):
|
def showContextMenu(self) -> None:
|
||||||
opts = self._contextMenu()
|
opts = self._contextMenu()
|
||||||
m = QMenu(self.mw)
|
m = QMenu(self.mw)
|
||||||
self._addMenuItems(m, opts)
|
self._addMenuItems(m, opts)
|
||||||
|
|
|
@ -23,7 +23,7 @@ class StudyDeck(QDialog):
|
||||||
dyn=False,
|
dyn=False,
|
||||||
buttons=None,
|
buttons=None,
|
||||||
geomKey="default",
|
geomKey="default",
|
||||||
):
|
) -> None:
|
||||||
QDialog.__init__(self, parent or mw)
|
QDialog.__init__(self, parent or mw)
|
||||||
if buttons is None:
|
if buttons is None:
|
||||||
buttons = []
|
buttons = []
|
||||||
|
@ -118,7 +118,7 @@ class StudyDeck(QDialog):
|
||||||
self.origNames = self.nameFunc()
|
self.origNames = self.nameFunc()
|
||||||
self.redraw(self.filt, self.focus)
|
self.redraw(self.filt, self.focus)
|
||||||
|
|
||||||
def accept(self):
|
def accept(self) -> None:
|
||||||
saveGeom(self, self.geomKey)
|
saveGeom(self, self.geomKey)
|
||||||
gui_hooks.state_did_reset.remove(self.onReset)
|
gui_hooks.state_did_reset.remove(self.onReset)
|
||||||
row = self.form.list.currentRow()
|
row = self.form.list.currentRow()
|
||||||
|
@ -128,12 +128,12 @@ class StudyDeck(QDialog):
|
||||||
self.name = self.names[self.form.list.currentRow()]
|
self.name = self.names[self.form.list.currentRow()]
|
||||||
QDialog.accept(self)
|
QDialog.accept(self)
|
||||||
|
|
||||||
def reject(self):
|
def reject(self) -> None:
|
||||||
saveGeom(self, self.geomKey)
|
saveGeom(self, self.geomKey)
|
||||||
gui_hooks.state_did_reset.remove(self.onReset)
|
gui_hooks.state_did_reset.remove(self.onReset)
|
||||||
QDialog.reject(self)
|
QDialog.reject(self)
|
||||||
|
|
||||||
def onAddDeck(self):
|
def onAddDeck(self) -> None:
|
||||||
row = self.form.list.currentRow()
|
row = self.form.list.currentRow()
|
||||||
if row < 0:
|
if row < 0:
|
||||||
default = self.form.filter.text()
|
default = self.form.filter.text()
|
||||||
|
|
|
@ -178,10 +178,10 @@ class AnkiWebView(QWebEngineView): # type: ignore
|
||||||
def onSelectAll(self):
|
def onSelectAll(self):
|
||||||
self.triggerPageAction(QWebEnginePage.SelectAll)
|
self.triggerPageAction(QWebEnginePage.SelectAll)
|
||||||
|
|
||||||
def contextMenuEvent(self, evt):
|
def contextMenuEvent(self, evt) -> None:
|
||||||
m = QMenu(self)
|
m = QMenu(self)
|
||||||
a = m.addAction(_("Copy"))
|
a = m.addAction(_("Copy"))
|
||||||
a.triggered.connect(self.onCopy)
|
a.triggered.connect(self.onCopy) # type: ignore
|
||||||
gui_hooks.webview_will_show_context_menu(self, m)
|
gui_hooks.webview_will_show_context_menu(self, m)
|
||||||
m.popup(QCursor.pos())
|
m.popup(QCursor.pos())
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue