add types to various other files
Mainly automated with MonkeyType
This commit is contained in:
parent
84f8d7f604
commit
f15715fb07
@ -137,7 +137,7 @@ class AddCards(QDialog):
|
||||
def removeTempNote(self, note: Note) -> None:
|
||||
print("removeTempNote() will go away")
|
||||
|
||||
def addHistory(self, note):
|
||||
def addHistory(self, note: Note) -> None:
|
||||
self.history.insert(0, note.id)
|
||||
self.history = self.history[:15]
|
||||
self.historyButton.setEnabled(True)
|
||||
@ -186,10 +186,10 @@ class AddCards(QDialog):
|
||||
gui_hooks.add_cards_did_add_note(note)
|
||||
return note
|
||||
|
||||
def addCards(self):
|
||||
def addCards(self) -> None:
|
||||
self.editor.saveNow(self._addCards)
|
||||
|
||||
def _addCards(self):
|
||||
def _addCards(self) -> None:
|
||||
self.editor.saveAddModeVars()
|
||||
if not self.addNote(self.editor.note):
|
||||
return
|
||||
@ -202,7 +202,7 @@ class AddCards(QDialog):
|
||||
self.onReset(keep=True)
|
||||
self.mw.col.autosave()
|
||||
|
||||
def keyPressEvent(self, evt):
|
||||
def keyPressEvent(self, evt: QKeyEvent) -> None:
|
||||
"Show answer on RET or register answer."
|
||||
if evt.key() in (Qt.Key_Enter, Qt.Key_Return) and self.editor.tags.hasFocus():
|
||||
evt.accept()
|
||||
|
@ -14,6 +14,7 @@ from anki.lang import without_unicode_isolation
|
||||
from anki.notes import Note
|
||||
from anki.template import TemplateRenderContext
|
||||
from aqt import AnkiQt, gui_hooks
|
||||
from aqt.forms.browserdisp import Ui_Dialog
|
||||
from aqt.qt import *
|
||||
from aqt.schema_change_tracker import ChangeTracker
|
||||
from aqt.sound import av_player, play_clicked_audio
|
||||
@ -90,7 +91,7 @@ class CardLayout(QDialog):
|
||||
# as users tend to accidentally type into the template
|
||||
self.setFocus()
|
||||
|
||||
def redraw_everything(self):
|
||||
def redraw_everything(self) -> None:
|
||||
self.ignore_change_signals = True
|
||||
self.updateTopArea()
|
||||
self.ignore_change_signals = False
|
||||
@ -104,13 +105,13 @@ class CardLayout(QDialog):
|
||||
self.fill_fields_from_template()
|
||||
self.renderPreview()
|
||||
|
||||
def _isCloze(self):
|
||||
def _isCloze(self) -> bool:
|
||||
return self.model["type"] == MODEL_CLOZE
|
||||
|
||||
# Top area
|
||||
##########################################################################
|
||||
|
||||
def setupTopArea(self):
|
||||
def setupTopArea(self) -> None:
|
||||
self.topArea = QWidget()
|
||||
self.topArea.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
|
||||
self.topAreaForm = aqt.forms.clayout_top.Ui_Form()
|
||||
@ -125,10 +126,10 @@ class CardLayout(QDialog):
|
||||
)
|
||||
self.topAreaForm.card_type_label.setText(tr(TR.CARD_TEMPLATES_CARD_TYPE))
|
||||
|
||||
def updateTopArea(self):
|
||||
def updateTopArea(self) -> None:
|
||||
self.updateCardNames()
|
||||
|
||||
def updateCardNames(self):
|
||||
def updateCardNames(self) -> None:
|
||||
self.ignore_change_signals = True
|
||||
combo = self.topAreaForm.templatesBox
|
||||
combo.clear()
|
||||
@ -170,7 +171,7 @@ class CardLayout(QDialog):
|
||||
s += "+..."
|
||||
return s
|
||||
|
||||
def setupShortcuts(self):
|
||||
def setupShortcuts(self) -> None:
|
||||
self.tform.front_button.setToolTip(shortcut("Ctrl+1"))
|
||||
self.tform.back_button.setToolTip(shortcut("Ctrl+2"))
|
||||
self.tform.style_button.setToolTip(shortcut("Ctrl+3"))
|
||||
@ -193,7 +194,7 @@ class CardLayout(QDialog):
|
||||
# Main area setup
|
||||
##########################################################################
|
||||
|
||||
def setupMainArea(self):
|
||||
def setupMainArea(self) -> None:
|
||||
split = self.mainArea = QSplitter()
|
||||
split.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
||||
split.setOrientation(Qt.Horizontal)
|
||||
@ -216,7 +217,7 @@ class CardLayout(QDialog):
|
||||
split.addWidget(right)
|
||||
split.setCollapsible(1, False)
|
||||
|
||||
def setup_edit_area(self):
|
||||
def setup_edit_area(self) -> None:
|
||||
tform = self.tform
|
||||
|
||||
tform.front_button.setText(tr(TR.CARD_TEMPLATES_FRONT_TEMPLATE))
|
||||
@ -248,7 +249,7 @@ class CardLayout(QDialog):
|
||||
qconnect(widg.textChanged, self.on_search_changed)
|
||||
qconnect(widg.returnPressed, self.on_search_next)
|
||||
|
||||
def setup_cloze_number_box(self):
|
||||
def setup_cloze_number_box(self) -> None:
|
||||
names = (tr(TR.CARD_TEMPLATES_CLOZE, val=n) for n in self.cloze_numbers)
|
||||
self.pform.cloze_number_combo.addItems(names)
|
||||
try:
|
||||
@ -266,7 +267,7 @@ class CardLayout(QDialog):
|
||||
self.have_autoplayed = False
|
||||
self._renderPreview()
|
||||
|
||||
def on_editor_toggled(self):
|
||||
def on_editor_toggled(self) -> None:
|
||||
if self.tform.front_button.isChecked():
|
||||
self.current_editor_index = 0
|
||||
self.pform.preview_front.setChecked(True)
|
||||
@ -297,7 +298,7 @@ class CardLayout(QDialog):
|
||||
text = self.tform.search_edit.text()
|
||||
self.on_search_changed(text)
|
||||
|
||||
def setup_preview(self):
|
||||
def setup_preview(self) -> None:
|
||||
pform = self.pform
|
||||
self.preview_web = AnkiWebView(title="card layout")
|
||||
pform.verticalLayout.addWidget(self.preview_web)
|
||||
@ -336,7 +337,7 @@ class CardLayout(QDialog):
|
||||
self.cloze_numbers = []
|
||||
self.pform.cloze_number_combo.setHidden(True)
|
||||
|
||||
def on_fill_empty_action_toggled(self):
|
||||
def on_fill_empty_action_toggled(self) -> None:
|
||||
self.fill_empty_action_toggled = not self.fill_empty_action_toggled
|
||||
self.on_preview_toggled()
|
||||
|
||||
@ -344,11 +345,11 @@ class CardLayout(QDialog):
|
||||
self.night_mode_is_enabled = not self.night_mode_is_enabled
|
||||
self.on_preview_toggled()
|
||||
|
||||
def on_mobile_class_action_toggled(self):
|
||||
def on_mobile_class_action_toggled(self) -> None:
|
||||
self.mobile_emulation_enabled = not self.mobile_emulation_enabled
|
||||
self.on_preview_toggled()
|
||||
|
||||
def on_preview_settings(self):
|
||||
def on_preview_settings(self) -> None:
|
||||
m = QMenu(self)
|
||||
|
||||
a = m.addAction(tr(TR.CARD_TEMPLATES_FILL_EMPTY))
|
||||
@ -370,7 +371,7 @@ class CardLayout(QDialog):
|
||||
|
||||
m.exec_(self.pform.preview_settings.mapToGlobal(QPoint(0, 0)))
|
||||
|
||||
def on_preview_toggled(self):
|
||||
def on_preview_toggled(self) -> None:
|
||||
self.have_autoplayed = False
|
||||
self._renderPreview()
|
||||
|
||||
@ -388,7 +389,7 @@ class CardLayout(QDialog):
|
||||
# Buttons
|
||||
##########################################################################
|
||||
|
||||
def setupButtons(self):
|
||||
def setupButtons(self) -> None:
|
||||
l = self.buttons = QHBoxLayout()
|
||||
help = QPushButton(tr(TR.ACTIONS_HELP))
|
||||
help.setAutoDefault(False)
|
||||
@ -424,7 +425,7 @@ class CardLayout(QDialog):
|
||||
return self.templates[0]
|
||||
return self.templates[self.ord]
|
||||
|
||||
def fill_fields_from_template(self):
|
||||
def fill_fields_from_template(self) -> None:
|
||||
t = self.current_template()
|
||||
self.ignore_change_signals = True
|
||||
|
||||
@ -438,7 +439,7 @@ class CardLayout(QDialog):
|
||||
self.tform.edit_area.setPlainText(text)
|
||||
self.ignore_change_signals = False
|
||||
|
||||
def write_edits_to_template_and_redraw(self):
|
||||
def write_edits_to_template_and_redraw(self) -> None:
|
||||
if self.ignore_change_signals:
|
||||
return
|
||||
|
||||
@ -458,14 +459,14 @@ class CardLayout(QDialog):
|
||||
# Preview
|
||||
##########################################################################
|
||||
|
||||
_previewTimer = None
|
||||
_previewTimer: Optional[QTimer] = None
|
||||
|
||||
def renderPreview(self):
|
||||
def renderPreview(self) -> None:
|
||||
# schedule a preview when timing stops
|
||||
self.cancelPreviewTimer()
|
||||
self._previewTimer = self.mw.progress.timer(200, self._renderPreview, False)
|
||||
|
||||
def cancelPreviewTimer(self):
|
||||
def cancelPreviewTimer(self) -> None:
|
||||
if self._previewTimer:
|
||||
self._previewTimer.stop()
|
||||
self._previewTimer = None
|
||||
@ -512,7 +513,7 @@ class CardLayout(QDialog):
|
||||
|
||||
self.updateCardNames()
|
||||
|
||||
def maybeTextInput(self, txt, type="q"):
|
||||
def maybeTextInput(self, txt: str, type: str = "q") -> str:
|
||||
if "[[type:" not in txt:
|
||||
return txt
|
||||
origLen = len(txt)
|
||||
@ -668,7 +669,7 @@ class CardLayout(QDialog):
|
||||
dst["qfmt"] = m.group(2).strip()
|
||||
return True
|
||||
|
||||
def onMore(self):
|
||||
def onMore(self) -> None:
|
||||
m = QMenu(self)
|
||||
|
||||
if not self._isCloze():
|
||||
@ -699,7 +700,7 @@ class CardLayout(QDialog):
|
||||
|
||||
m.exec_(self.topAreaForm.templateOptions.mapToGlobal(QPoint(0, 0)))
|
||||
|
||||
def onBrowserDisplay(self):
|
||||
def onBrowserDisplay(self) -> None:
|
||||
d = QDialog()
|
||||
disable_help_button(d)
|
||||
f = aqt.forms.browserdisp.Ui_Dialog()
|
||||
@ -714,7 +715,7 @@ class CardLayout(QDialog):
|
||||
qconnect(f.buttonBox.accepted, lambda: self.onBrowserDisplayOk(f))
|
||||
d.exec_()
|
||||
|
||||
def onBrowserDisplayOk(self, f):
|
||||
def onBrowserDisplayOk(self, f: Ui_Dialog) -> None:
|
||||
t = self.current_template()
|
||||
self.change_tracker.mark_basic()
|
||||
t["bqfmt"] = f.qfmt.text().strip()
|
||||
|
@ -1,6 +1,7 @@
|
||||
# Copyright: Ankitects Pty Ltd and contributors
|
||||
# -*- coding: utf-8 -*-
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
import aqt
|
||||
from anki.collection import SearchTerm
|
||||
from anki.consts import *
|
||||
@ -35,7 +36,7 @@ class CustomStudy(QDialog):
|
||||
f.radioNew.click()
|
||||
self.exec_()
|
||||
|
||||
def setupSignals(self):
|
||||
def setupSignals(self) -> None:
|
||||
f = self.form
|
||||
qconnect(f.radioNew.clicked, lambda: self.onRadioChange(RADIO_NEW))
|
||||
qconnect(f.radioRev.clicked, lambda: self.onRadioChange(RADIO_REV))
|
||||
@ -44,7 +45,7 @@ class CustomStudy(QDialog):
|
||||
qconnect(f.radioPreview.clicked, lambda: self.onRadioChange(RADIO_PREVIEW))
|
||||
qconnect(f.radioCram.clicked, lambda: self.onRadioChange(RADIO_CRAM))
|
||||
|
||||
def onRadioChange(self, idx):
|
||||
def onRadioChange(self, idx: int) -> None:
|
||||
f = self.form
|
||||
sp = f.spin
|
||||
smin = 1
|
||||
@ -123,7 +124,7 @@ class CustomStudy(QDialog):
|
||||
f.buttonBox.button(QDialogButtonBox.Ok).setText(ok)
|
||||
self.radioIdx = idx
|
||||
|
||||
def accept(self):
|
||||
def accept(self) -> None:
|
||||
f = self.form
|
||||
i = self.radioIdx
|
||||
spin = f.spin.value()
|
||||
@ -132,13 +133,15 @@ class CustomStudy(QDialog):
|
||||
self.mw.col.decks.save(self.deck)
|
||||
self.mw.col.sched.extendLimits(spin, 0)
|
||||
self.mw.reset()
|
||||
return QDialog.accept(self)
|
||||
QDialog.accept(self)
|
||||
return
|
||||
elif i == RADIO_REV:
|
||||
self.deck["extendRev"] = spin
|
||||
self.mw.col.decks.save(self.deck)
|
||||
self.mw.col.sched.extendLimits(0, spin)
|
||||
self.mw.reset()
|
||||
return QDialog.accept(self)
|
||||
QDialog.accept(self)
|
||||
return
|
||||
elif i == RADIO_CRAM:
|
||||
tags = self._getTags()
|
||||
# the rest create a filtered deck
|
||||
@ -146,7 +149,8 @@ class CustomStudy(QDialog):
|
||||
if cur:
|
||||
if not cur["dyn"]:
|
||||
showInfo(tr(TR.CUSTOM_STUDY_MUST_RENAME_DECK))
|
||||
return QDialog.accept(self)
|
||||
QDialog.accept(self)
|
||||
return
|
||||
else:
|
||||
# safe to empty
|
||||
self.mw.col.sched.empty_filtered_deck(cur["id"])
|
||||
@ -211,7 +215,8 @@ class CustomStudy(QDialog):
|
||||
# generate cards
|
||||
self.created_custom_study = True
|
||||
if not self.mw.col.sched.rebuild_filtered_deck(dyn["id"]):
|
||||
return showWarning(tr(TR.CUSTOM_STUDY_NO_CARDS_MATCHED_THE_CRITERIA_YOU))
|
||||
showWarning(tr(TR.CUSTOM_STUDY_NO_CARDS_MATCHED_THE_CRITERIA_YOU))
|
||||
return
|
||||
self.mw.moveToState("overview")
|
||||
QDialog.accept(self)
|
||||
|
||||
@ -222,7 +227,7 @@ class CustomStudy(QDialog):
|
||||
# fixme: clean up the empty custom study deck
|
||||
QDialog.reject(self)
|
||||
|
||||
def _getTags(self):
|
||||
def _getTags(self) -> str:
|
||||
from aqt.taglimit import TagLimit
|
||||
|
||||
return TagLimit(self.mw, self).tags
|
||||
|
@ -1,12 +1,13 @@
|
||||
# Copyright: Ankitects Pty Ltd and contributors
|
||||
# -*- coding: utf-8 -*-
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
from typing import List, Optional
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
import aqt
|
||||
from anki.collection import SearchTerm
|
||||
from anki.errors import InvalidInput
|
||||
from anki.lang import without_unicode_isolation
|
||||
from aqt.main import AnkiQt
|
||||
from aqt.qt import *
|
||||
from aqt.utils import (
|
||||
TR,
|
||||
@ -23,7 +24,13 @@ from aqt.utils import (
|
||||
|
||||
|
||||
class DeckConf(QDialog):
|
||||
def __init__(self, mw, first=False, search="", deck=None):
|
||||
def __init__(
|
||||
self,
|
||||
mw: AnkiQt,
|
||||
first: bool = False,
|
||||
search: str = "",
|
||||
deck: Optional[Dict] = None,
|
||||
) -> None:
|
||||
QDialog.__init__(self, mw)
|
||||
self.mw = mw
|
||||
self.deck = deck or self.mw.col.decks.current()
|
||||
@ -65,7 +72,7 @@ class DeckConf(QDialog):
|
||||
self.exec_()
|
||||
saveGeom(self, "dyndeckconf")
|
||||
|
||||
def initialSetup(self):
|
||||
def initialSetup(self) -> None:
|
||||
import anki.consts as cs
|
||||
|
||||
self.form.order.addItems(list(cs.dynOrderLabels(self.mw.col).values()))
|
||||
@ -73,12 +80,12 @@ class DeckConf(QDialog):
|
||||
|
||||
qconnect(self.form.resched.stateChanged, self._onReschedToggled)
|
||||
|
||||
def _onReschedToggled(self, _state):
|
||||
def _onReschedToggled(self, _state: int) -> None:
|
||||
self.form.previewDelayWidget.setVisible(
|
||||
not self.form.resched.isChecked() and self.mw.col.schedVer() > 1
|
||||
)
|
||||
|
||||
def loadConf(self):
|
||||
def loadConf(self) -> None:
|
||||
f = self.form
|
||||
d = self.deck
|
||||
|
||||
@ -113,7 +120,7 @@ class DeckConf(QDialog):
|
||||
f.secondFilter.setChecked(False)
|
||||
f.filter2group.setVisible(False)
|
||||
|
||||
def saveConf(self):
|
||||
def saveConf(self) -> None:
|
||||
f = self.form
|
||||
d = self.deck
|
||||
d["resched"] = f.resched.isChecked()
|
||||
@ -142,7 +149,7 @@ class DeckConf(QDialog):
|
||||
self.ok = False
|
||||
QDialog.reject(self)
|
||||
|
||||
def accept(self):
|
||||
def accept(self) -> None:
|
||||
try:
|
||||
self.saveConf()
|
||||
except InvalidInput as err:
|
||||
|
@ -52,10 +52,10 @@ class EditCurrent(QDialog):
|
||||
tooltip("Please finish editing the existing card first.")
|
||||
self.onReset()
|
||||
|
||||
def reject(self):
|
||||
def reject(self) -> None:
|
||||
self.saveAndClose()
|
||||
|
||||
def saveAndClose(self):
|
||||
def saveAndClose(self) -> None:
|
||||
self.editor.saveNow(self._saveAndClose)
|
||||
|
||||
def _saveAndClose(self) -> None:
|
||||
|
@ -68,7 +68,7 @@ class EmptyCardsDialog(QDialog):
|
||||
def _on_note_link_clicked(self, link):
|
||||
self.mw.browser_search(link)
|
||||
|
||||
def _on_delete(self):
|
||||
def _on_delete(self) -> None:
|
||||
self.mw.progress.start()
|
||||
|
||||
def delete():
|
||||
|
@ -5,10 +5,12 @@ import html
|
||||
import re
|
||||
import sys
|
||||
import traceback
|
||||
from typing import Optional
|
||||
|
||||
from markdown import markdown
|
||||
|
||||
from aqt import mw
|
||||
from aqt.main import AnkiQt
|
||||
from aqt.qt import *
|
||||
from aqt.utils import TR, showText, showWarning, supportText, tr
|
||||
|
||||
@ -29,20 +31,20 @@ class ErrorHandler(QObject):
|
||||
|
||||
errorTimer = pyqtSignal()
|
||||
|
||||
def __init__(self, mw):
|
||||
def __init__(self, mw: AnkiQt) -> None:
|
||||
QObject.__init__(self, mw)
|
||||
self.mw = mw
|
||||
self.timer = None
|
||||
self.timer: Optional[QTimer] = None
|
||||
qconnect(self.errorTimer, self._setTimer)
|
||||
self.pool = ""
|
||||
self._oldstderr = sys.stderr
|
||||
sys.stderr = self
|
||||
|
||||
def unload(self):
|
||||
def unload(self) -> None:
|
||||
sys.stderr = self._oldstderr
|
||||
sys.excepthook = None
|
||||
|
||||
def write(self, data):
|
||||
def write(self, data: str) -> None:
|
||||
# dump to stdout
|
||||
sys.stdout.write(data)
|
||||
# save in buffer
|
||||
@ -50,12 +52,12 @@ class ErrorHandler(QObject):
|
||||
# and update timer
|
||||
self.setTimer()
|
||||
|
||||
def setTimer(self):
|
||||
def setTimer(self) -> None:
|
||||
# we can't create a timer from a different thread, so we post a
|
||||
# message to the object on the main thread
|
||||
self.errorTimer.emit() # type: ignore
|
||||
|
||||
def _setTimer(self):
|
||||
def _setTimer(self) -> None:
|
||||
if not self.timer:
|
||||
self.timer = QTimer(self.mw)
|
||||
qconnect(self.timer.timeout, self.onTimeout)
|
||||
@ -66,7 +68,7 @@ class ErrorHandler(QObject):
|
||||
def tempFolderMsg(self):
|
||||
return tr(TR.QT_MISC_UNABLE_TO_ACCESS_ANKI_MEDIA_FOLDER)
|
||||
|
||||
def onTimeout(self):
|
||||
def onTimeout(self) -> None:
|
||||
error = html.escape(self.pool)
|
||||
self.pool = ""
|
||||
self.mw.progress.clear()
|
||||
@ -75,15 +77,19 @@ class ErrorHandler(QObject):
|
||||
if "DeprecationWarning" in error:
|
||||
return
|
||||
if "10013" in error:
|
||||
return showWarning(tr(TR.QT_MISC_YOUR_FIREWALL_OR_ANTIVIRUS_PROGRAM_IS))
|
||||
showWarning(tr(TR.QT_MISC_YOUR_FIREWALL_OR_ANTIVIRUS_PROGRAM_IS))
|
||||
return
|
||||
if "no default input" in error.lower():
|
||||
return showWarning(tr(TR.QT_MISC_PLEASE_CONNECT_A_MICROPHONE_AND_ENSURE))
|
||||
showWarning(tr(TR.QT_MISC_PLEASE_CONNECT_A_MICROPHONE_AND_ENSURE))
|
||||
return
|
||||
if "invalidTempFolder" in error:
|
||||
return showWarning(self.tempFolderMsg())
|
||||
showWarning(self.tempFolderMsg())
|
||||
return
|
||||
if "Beautiful Soup is not an HTTP client" in error:
|
||||
return
|
||||
if "database or disk is full" in error or "Errno 28" in error:
|
||||
return showWarning(tr(TR.QT_MISC_YOUR_COMPUTERS_STORAGE_MAY_BE_FULL))
|
||||
showWarning(tr(TR.QT_MISC_YOUR_COMPUTERS_STORAGE_MAY_BE_FULL))
|
||||
return
|
||||
if "disk I/O error" in error:
|
||||
showWarning(markdown(tr(TR.ERRORS_ACCESSING_DB)))
|
||||
return
|
||||
|
@ -71,7 +71,7 @@ class ExportDialog(QDialog):
|
||||
index = self.frm.deck.findText(name)
|
||||
self.frm.deck.setCurrentIndex(index)
|
||||
|
||||
def exporterChanged(self, idx):
|
||||
def exporterChanged(self, idx: int) -> None:
|
||||
self.exporter = self.exporters[idx][1](self.col)
|
||||
self.isApkg = self.exporter.ext == ".apkg"
|
||||
self.isVerbatim = getattr(self.exporter, "verbatim", False)
|
||||
@ -94,7 +94,7 @@ class ExportDialog(QDialog):
|
||||
# show deck list?
|
||||
self.frm.deck.setVisible(not self.isVerbatim)
|
||||
|
||||
def accept(self):
|
||||
def accept(self) -> None:
|
||||
self.exporter.includeSched = self.frm.includeSched.isChecked()
|
||||
self.exporter.includeMedia = self.frm.includeMedia.isChecked()
|
||||
self.exporter.includeTags = self.frm.includeTags.isChecked()
|
||||
@ -177,7 +177,7 @@ class ExportDialog(QDialog):
|
||||
|
||||
self.mw.taskman.run_in_background(do_export, on_done)
|
||||
|
||||
def on_export_finished(self):
|
||||
def on_export_finished(self) -> None:
|
||||
if self.isVerbatim:
|
||||
msg = tr(TR.EXPORTING_COLLECTION_EXPORTED)
|
||||
self.mw.reopen()
|
||||
|
@ -41,7 +41,7 @@ class FieldDialog(QDialog):
|
||||
self.form.buttonBox.button(QDialogButtonBox.Help).setAutoDefault(False)
|
||||
self.form.buttonBox.button(QDialogButtonBox.Cancel).setAutoDefault(False)
|
||||
self.form.buttonBox.button(QDialogButtonBox.Save).setAutoDefault(False)
|
||||
self.currentIdx = None
|
||||
self.currentIdx: Optional[int] = None
|
||||
self.oldSortField = self.model["sortf"]
|
||||
self.fillFields()
|
||||
self.setupSignals()
|
||||
@ -52,13 +52,13 @@ class FieldDialog(QDialog):
|
||||
|
||||
##########################################################################
|
||||
|
||||
def fillFields(self):
|
||||
def fillFields(self) -> None:
|
||||
self.currentIdx = None
|
||||
self.form.fieldList.clear()
|
||||
for c, f in enumerate(self.model["flds"]):
|
||||
self.form.fieldList.addItem("{}: {}".format(c + 1, f["name"]))
|
||||
|
||||
def setupSignals(self):
|
||||
def setupSignals(self) -> None:
|
||||
f = self.form
|
||||
qconnect(f.fieldList.currentRowChanged, self.onRowChange)
|
||||
qconnect(f.fieldAdd.clicked, self.onAdd)
|
||||
@ -86,29 +86,31 @@ class FieldDialog(QDialog):
|
||||
movePos -= 1
|
||||
self.moveField(movePos + 1) # convert to 1 based.
|
||||
|
||||
def onRowChange(self, idx):
|
||||
def onRowChange(self, idx: int) -> None:
|
||||
if idx == -1:
|
||||
return
|
||||
self.saveField()
|
||||
self.loadField(idx)
|
||||
|
||||
def _uniqueName(self, prompt, ignoreOrd=None, old=""):
|
||||
def _uniqueName(
|
||||
self, prompt: str, ignoreOrd: Optional[int] = None, old: str = ""
|
||||
) -> Optional[str]:
|
||||
txt = getOnlyText(prompt, default=old).replace('"', "").strip()
|
||||
if not txt:
|
||||
return
|
||||
return None
|
||||
if txt[0] in "#^/":
|
||||
showWarning(tr(TR.FIELDS_NAME_FIRST_LETTER_NOT_VALID))
|
||||
return
|
||||
return None
|
||||
for letter in """:{"}""":
|
||||
if letter in txt:
|
||||
showWarning(tr(TR.FIELDS_NAME_INVALID_LETTER))
|
||||
return
|
||||
return None
|
||||
for f in self.model["flds"]:
|
||||
if ignoreOrd is not None and f["ord"] == ignoreOrd:
|
||||
continue
|
||||
if f["name"] == txt:
|
||||
showWarning(tr(TR.FIELDS_THAT_FIELD_NAME_IS_ALREADY_USED))
|
||||
return
|
||||
return None
|
||||
return txt
|
||||
|
||||
def onRename(self):
|
||||
@ -127,7 +129,7 @@ class FieldDialog(QDialog):
|
||||
self.fillFields()
|
||||
self.form.fieldList.setCurrentRow(idx)
|
||||
|
||||
def onAdd(self):
|
||||
def onAdd(self) -> None:
|
||||
name = self._uniqueName(tr(TR.FIELDS_FIELD_NAME))
|
||||
if not name:
|
||||
return
|
||||
@ -185,7 +187,7 @@ class FieldDialog(QDialog):
|
||||
self.fillFields()
|
||||
self.form.fieldList.setCurrentRow(pos - 1)
|
||||
|
||||
def loadField(self, idx):
|
||||
def loadField(self, idx: int) -> None:
|
||||
self.currentIdx = idx
|
||||
fld = self.model["flds"][idx]
|
||||
f = self.form
|
||||
@ -195,7 +197,7 @@ class FieldDialog(QDialog):
|
||||
f.sortField.setChecked(self.model["sortf"] == fld["ord"])
|
||||
f.rtl.setChecked(fld["rtl"])
|
||||
|
||||
def saveField(self):
|
||||
def saveField(self) -> None:
|
||||
# not initialized yet?
|
||||
if self.currentIdx is None:
|
||||
return
|
||||
@ -219,14 +221,14 @@ class FieldDialog(QDialog):
|
||||
fld["rtl"] = rtl
|
||||
self.change_tracker.mark_basic()
|
||||
|
||||
def reject(self):
|
||||
def reject(self) -> None:
|
||||
if self.change_tracker.changed():
|
||||
if not askUser("Discard changes?"):
|
||||
return
|
||||
|
||||
QDialog.reject(self)
|
||||
|
||||
def accept(self):
|
||||
def accept(self) -> None:
|
||||
self.saveField()
|
||||
|
||||
def save():
|
||||
|
@ -9,12 +9,13 @@ import traceback
|
||||
import unicodedata
|
||||
import zipfile
|
||||
from concurrent.futures import Future
|
||||
from typing import Optional
|
||||
from typing import Any, Optional
|
||||
|
||||
import anki.importing as importing
|
||||
import aqt.deckchooser
|
||||
import aqt.forms
|
||||
import aqt.modelchooser
|
||||
from anki.importing.apkg import AnkiPackageImporter
|
||||
from aqt import AnkiQt, gui_hooks
|
||||
from aqt.qt import *
|
||||
from aqt.utils import (
|
||||
@ -106,14 +107,14 @@ class ImportDialog(QDialog):
|
||||
self.frm.buttonBox.addButton(b, QDialogButtonBox.AcceptRole)
|
||||
self.exec_()
|
||||
|
||||
def setupOptions(self):
|
||||
def setupOptions(self) -> None:
|
||||
self.model = self.mw.col.models.current()
|
||||
self.modelChooser = aqt.modelchooser.ModelChooser(
|
||||
self.mw, self.frm.modelArea, label=False
|
||||
)
|
||||
self.deck = aqt.deckchooser.DeckChooser(self.mw, self.frm.deckArea, label=False)
|
||||
|
||||
def modelChanged(self, unused=None):
|
||||
def modelChanged(self, unused: Any = None) -> None:
|
||||
self.importer.model = self.mw.col.models.current()
|
||||
self.importer.initMapping()
|
||||
self.showMapping()
|
||||
@ -142,7 +143,7 @@ class ImportDialog(QDialog):
|
||||
self.showMapping(hook=updateDelim)
|
||||
self.updateDelimiterButtonText()
|
||||
|
||||
def updateDelimiterButtonText(self):
|
||||
def updateDelimiterButtonText(self) -> None:
|
||||
if not self.importer.needDelimiter:
|
||||
return
|
||||
if self.importer.delimiter:
|
||||
@ -164,7 +165,7 @@ class ImportDialog(QDialog):
|
||||
txt = tr(TR.IMPORTING_FIELDS_SEPARATED_BY, val=d)
|
||||
self.frm.autoDetect.setText(txt)
|
||||
|
||||
def accept(self):
|
||||
def accept(self) -> None:
|
||||
self.importer.mapping = self.mapping
|
||||
if not self.importer.mappingOk():
|
||||
showWarning(tr(TR.IMPORTING_THE_FIRST_FIELD_OF_THE_NOTE))
|
||||
@ -211,19 +212,21 @@ class ImportDialog(QDialog):
|
||||
|
||||
self.mw.taskman.run_in_background(self.importer.run, on_done)
|
||||
|
||||
def setupMappingFrame(self):
|
||||
def setupMappingFrame(self) -> None:
|
||||
# qt seems to have a bug with adding/removing from a grid, so we add
|
||||
# to a separate object and add/remove that instead
|
||||
self.frame = QFrame(self.frm.mappingArea)
|
||||
self.frm.mappingArea.setWidget(self.frame)
|
||||
self.mapbox = QVBoxLayout(self.frame)
|
||||
self.mapbox.setContentsMargins(0, 0, 0, 0)
|
||||
self.mapwidget = None
|
||||
self.mapwidget: Optional[QWidget] = None
|
||||
|
||||
def hideMapping(self):
|
||||
self.frm.mappingGroup.hide()
|
||||
|
||||
def showMapping(self, keepMapping=False, hook=None):
|
||||
def showMapping(
|
||||
self, keepMapping: bool = False, hook: Optional[Callable] = None
|
||||
) -> None:
|
||||
if hook:
|
||||
hook()
|
||||
if not keepMapping:
|
||||
@ -295,7 +298,7 @@ def showUnicodeWarning():
|
||||
showWarning(tr(TR.IMPORTING_SELECTED_FILE_WAS_NOT_IN_UTF8))
|
||||
|
||||
|
||||
def onImport(mw):
|
||||
def onImport(mw: AnkiQt) -> None:
|
||||
filt = ";;".join([x[0] for x in importing.Importers])
|
||||
file = getFile(mw, tr(TR.ACTIONS_IMPORT), None, key="import", filter=filt)
|
||||
if not file:
|
||||
@ -314,7 +317,7 @@ def onImport(mw):
|
||||
importFile(mw, file)
|
||||
|
||||
|
||||
def importFile(mw, file):
|
||||
def importFile(mw: AnkiQt, file: str) -> None:
|
||||
importerClass = None
|
||||
done = False
|
||||
for i in importing.Importers:
|
||||
@ -406,7 +409,7 @@ def invalidZipMsg():
|
||||
return tr(TR.IMPORTING_THIS_FILE_DOES_NOT_APPEAR_TO)
|
||||
|
||||
|
||||
def setupApkgImport(mw, importer):
|
||||
def setupApkgImport(mw: AnkiQt, importer: AnkiPackageImporter) -> bool:
|
||||
base = os.path.basename(importer.file).lower()
|
||||
full = (
|
||||
(base == "collection.apkg")
|
||||
@ -424,6 +427,7 @@ def setupApkgImport(mw, importer):
|
||||
return False
|
||||
|
||||
replaceWithApkg(mw, importer.file, mw.restoringBackup)
|
||||
return False
|
||||
|
||||
|
||||
def replaceWithApkg(mw, file, backup):
|
||||
|
@ -1141,7 +1141,7 @@ title="%s" %s>%s</button>""" % (
|
||||
# Cramming
|
||||
##########################################################################
|
||||
|
||||
def onCram(self, search=""):
|
||||
def onCram(self, search: str = "") -> None:
|
||||
import aqt.dyndeckconf
|
||||
|
||||
n = 1
|
||||
|
@ -26,7 +26,7 @@ from aqt.qt import *
|
||||
from aqt.utils import aqt_data_folder
|
||||
|
||||
|
||||
def _getExportFolder():
|
||||
def _getExportFolder() -> str:
|
||||
data_folder = aqt_data_folder()
|
||||
webInSrcFolder = os.path.abspath(os.path.join(data_folder, "web"))
|
||||
if os.path.exists(webInSrcFolder):
|
||||
@ -83,7 +83,7 @@ class MediaServer(threading.Thread):
|
||||
if not self.is_shutdown:
|
||||
raise
|
||||
|
||||
def shutdown(self):
|
||||
def shutdown(self) -> None:
|
||||
self.is_shutdown = True
|
||||
sockets = list(self.server._map.values()) # type: ignore
|
||||
for socket in sockets:
|
||||
@ -91,7 +91,7 @@ class MediaServer(threading.Thread):
|
||||
# https://github.com/Pylons/webtest/blob/4b8a3ebf984185ff4fefb31b4d0cf82682e1fcf7/webtest/http.py#L93-L104
|
||||
self.server.task_dispatcher.shutdown()
|
||||
|
||||
def getPort(self):
|
||||
def getPort(self) -> int:
|
||||
self._ready.wait()
|
||||
return int(self.server.effective_port) # type: ignore
|
||||
|
||||
|
@ -57,7 +57,7 @@ class Models(QDialog):
|
||||
# Models
|
||||
##########################################################################
|
||||
|
||||
def maybe_select_provided_notetype(self):
|
||||
def maybe_select_provided_notetype(self) -> None:
|
||||
if not self.selected_notetype_id:
|
||||
self.form.modelsList.setCurrentRow(0)
|
||||
return
|
||||
|
@ -4,7 +4,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
from typing import Any, Callable, Dict, List, Optional, Tuple
|
||||
|
||||
import aqt
|
||||
from anki.collection import SearchTerm
|
||||
@ -45,13 +45,13 @@ class Overview:
|
||||
self.web = mw.web
|
||||
self.bottom = BottomBar(mw, mw.bottomWeb)
|
||||
|
||||
def show(self):
|
||||
def show(self) -> None:
|
||||
av_player.stop_and_clear_queue()
|
||||
self.web.set_bridge_command(self._linkHandler, self)
|
||||
self.mw.setStateShortcuts(self._shortcutKeys())
|
||||
self.refresh()
|
||||
|
||||
def refresh(self):
|
||||
def refresh(self) -> None:
|
||||
self.mw.col.reset()
|
||||
self._renderPage()
|
||||
self._renderBottom()
|
||||
@ -61,7 +61,7 @@ class Overview:
|
||||
# Handlers
|
||||
############################################################
|
||||
|
||||
def _linkHandler(self, url):
|
||||
def _linkHandler(self, url: str) -> bool:
|
||||
if url == "study":
|
||||
self.mw.col.startTimebox()
|
||||
self.mw.moveToState("review")
|
||||
@ -92,7 +92,7 @@ class Overview:
|
||||
openLink(url)
|
||||
return False
|
||||
|
||||
def _shortcutKeys(self):
|
||||
def _shortcutKeys(self) -> List[Tuple[str, Callable]]:
|
||||
return [
|
||||
("o", self.mw.onDeckConf),
|
||||
("r", self.onRebuildKey),
|
||||
@ -101,7 +101,7 @@ class Overview:
|
||||
("u", self.onUnbury),
|
||||
]
|
||||
|
||||
def _filteredDeck(self):
|
||||
def _filteredDeck(self) -> int:
|
||||
return self.mw.col.decks.current()["dyn"]
|
||||
|
||||
def onRebuildKey(self):
|
||||
@ -114,7 +114,7 @@ class Overview:
|
||||
self.mw.col.sched.empty_filtered_deck(self.mw.col.decks.selected())
|
||||
self.mw.reset()
|
||||
|
||||
def onCustomStudyKey(self):
|
||||
def onCustomStudyKey(self) -> None:
|
||||
if not self._filteredDeck():
|
||||
self.onStudyMore()
|
||||
|
||||
@ -150,7 +150,7 @@ class Overview:
|
||||
# HTML
|
||||
############################################################
|
||||
|
||||
def _renderPage(self):
|
||||
def _renderPage(self) -> None:
|
||||
but = self.mw.button
|
||||
deck = self.mw.col.decks.current()
|
||||
self.sid = deck.get("sharedFrom")
|
||||
@ -177,10 +177,10 @@ class Overview:
|
||||
context=self,
|
||||
)
|
||||
|
||||
def _show_finished_screen(self):
|
||||
def _show_finished_screen(self) -> None:
|
||||
self.web.load_ts_page("congrats")
|
||||
|
||||
def _desc(self, deck):
|
||||
def _desc(self, deck: Dict[str, Any]) -> str:
|
||||
if deck["dyn"]:
|
||||
desc = tr(TR.STUDYING_THIS_IS_A_SPECIAL_DECK_FOR)
|
||||
desc += " " + tr(TR.STUDYING_CARDS_WILL_BE_AUTOMATICALLY_RETURNED_TO)
|
||||
@ -229,7 +229,7 @@ class Overview:
|
||||
# Bottom area
|
||||
######################################################################
|
||||
|
||||
def _renderBottom(self):
|
||||
def _renderBottom(self) -> None:
|
||||
links = [
|
||||
["O", "opts", tr(TR.ACTIONS_OPTIONS)],
|
||||
]
|
||||
@ -256,7 +256,7 @@ class Overview:
|
||||
# Studying more
|
||||
######################################################################
|
||||
|
||||
def onStudyMore(self):
|
||||
def onStudyMore(self) -> None:
|
||||
import aqt.customstudy
|
||||
|
||||
aqt.customstudy.CustomStudy(self.mw)
|
||||
|
@ -4,7 +4,7 @@
|
||||
import json
|
||||
import re
|
||||
import time
|
||||
from typing import Any, Callable, Optional, Union
|
||||
from typing import Any, Callable, Optional, Tuple, Union
|
||||
|
||||
from anki.cards import Card
|
||||
from anki.collection import ConfigBoolKey
|
||||
@ -19,6 +19,7 @@ from aqt.qt import (
|
||||
QPixmap,
|
||||
QShortcut,
|
||||
Qt,
|
||||
QTimer,
|
||||
QVBoxLayout,
|
||||
QWidget,
|
||||
qconnect,
|
||||
@ -29,12 +30,14 @@ from aqt.theme import theme_manager
|
||||
from aqt.utils import TR, disable_help_button, restoreGeom, saveGeom, tr
|
||||
from aqt.webview import AnkiWebView
|
||||
|
||||
LastStateAndMod = Tuple[str, int, int]
|
||||
|
||||
|
||||
class Previewer(QDialog):
|
||||
_last_state = None
|
||||
_last_state: Optional[LastStateAndMod] = None
|
||||
_card_changed = False
|
||||
_last_render: Union[int, float] = 0
|
||||
_timer = None
|
||||
_timer: Optional[QTimer] = None
|
||||
_show_both_sides = False
|
||||
|
||||
def __init__(self, parent: QWidget, mw: AnkiQt, on_close: Callable[[], None]):
|
||||
@ -54,7 +57,7 @@ class Previewer(QDialog):
|
||||
def card_changed(self) -> bool:
|
||||
raise NotImplementedError
|
||||
|
||||
def open(self):
|
||||
def open(self) -> None:
|
||||
self._state = "question"
|
||||
self._last_state = None
|
||||
self._create_gui()
|
||||
@ -62,7 +65,7 @@ class Previewer(QDialog):
|
||||
self.render_card()
|
||||
self.show()
|
||||
|
||||
def _create_gui(self):
|
||||
def _create_gui(self) -> None:
|
||||
self.setWindowTitle(tr(TR.ACTIONS_PREVIEW))
|
||||
|
||||
self.close_shortcut = QShortcut(QKeySequence("Ctrl+Shift+P"), self)
|
||||
@ -98,25 +101,25 @@ class Previewer(QDialog):
|
||||
self.setLayout(self.vbox)
|
||||
restoreGeom(self, "preview")
|
||||
|
||||
def _on_finished(self, ok):
|
||||
def _on_finished(self, ok: int) -> None:
|
||||
saveGeom(self, "preview")
|
||||
self.mw.progress.timer(100, self._on_close, False)
|
||||
|
||||
def _on_replay_audio(self):
|
||||
def _on_replay_audio(self) -> None:
|
||||
if self._state == "question":
|
||||
replay_audio(self.card(), True)
|
||||
elif self._state == "answer":
|
||||
replay_audio(self.card(), False)
|
||||
|
||||
def close(self):
|
||||
def close(self) -> None:
|
||||
self._on_close()
|
||||
super().close()
|
||||
|
||||
def _on_close(self):
|
||||
def _on_close(self) -> None:
|
||||
self._open = False
|
||||
self._close_callback()
|
||||
|
||||
def _setup_web_view(self):
|
||||
def _setup_web_view(self) -> None:
|
||||
jsinc = [
|
||||
"js/vendor/jquery.min.js",
|
||||
"js/vendor/css_browser_selector.min.js",
|
||||
@ -136,7 +139,7 @@ class Previewer(QDialog):
|
||||
if cmd.startswith("play:"):
|
||||
play_clicked_audio(cmd, self.card())
|
||||
|
||||
def render_card(self):
|
||||
def render_card(self) -> None:
|
||||
self.cancel_timer()
|
||||
# Keep track of whether render() has ever been called
|
||||
# with cardChanged=True since the last successful render
|
||||
@ -151,7 +154,7 @@ class Previewer(QDialog):
|
||||
else:
|
||||
self._render_scheduled()
|
||||
|
||||
def cancel_timer(self):
|
||||
def cancel_timer(self) -> None:
|
||||
if self._timer:
|
||||
self._timer.stop()
|
||||
self._timer = None
|
||||
@ -214,7 +217,7 @@ class Previewer(QDialog):
|
||||
self._web.eval("{}({},'{}');".format(func, json.dumps(txt), bodyclass))
|
||||
self._card_changed = False
|
||||
|
||||
def _on_show_both_sides(self, toggle):
|
||||
def _on_show_both_sides(self, toggle: bool) -> None:
|
||||
self._show_both_sides = toggle
|
||||
self.mw.col.set_config_bool(ConfigBoolKey.PREVIEW_BOTH_SIDES, toggle)
|
||||
self.mw.col.setMod()
|
||||
@ -222,7 +225,7 @@ class Previewer(QDialog):
|
||||
self._state = "question"
|
||||
self.render_card()
|
||||
|
||||
def _state_and_mod(self):
|
||||
def _state_and_mod(self) -> Tuple[str, int, int]:
|
||||
c = self.card()
|
||||
n = c.note()
|
||||
n.load()
|
||||
@ -241,7 +244,7 @@ class MultiCardPreviewer(Previewer):
|
||||
# need to state explicitly it's not implement to avoid W0223
|
||||
raise NotImplementedError
|
||||
|
||||
def _create_gui(self):
|
||||
def _create_gui(self) -> None:
|
||||
super()._create_gui()
|
||||
self._prev = self.bbox.addButton("<", QDialogButtonBox.ActionRole)
|
||||
self._prev.setAutoDefault(False)
|
||||
@ -266,7 +269,7 @@ class MultiCardPreviewer(Previewer):
|
||||
def _on_prev_card(self):
|
||||
pass
|
||||
|
||||
def _on_next(self):
|
||||
def _on_next(self) -> None:
|
||||
if self._state == "question":
|
||||
self._state = "answer"
|
||||
self.render_card()
|
||||
@ -276,19 +279,19 @@ class MultiCardPreviewer(Previewer):
|
||||
def _on_next_card(self):
|
||||
pass
|
||||
|
||||
def _updateButtons(self):
|
||||
def _updateButtons(self) -> None:
|
||||
if not self._open:
|
||||
return
|
||||
self._prev.setEnabled(self._should_enable_prev())
|
||||
self._next.setEnabled(self._should_enable_next())
|
||||
|
||||
def _should_enable_prev(self):
|
||||
def _should_enable_prev(self) -> bool:
|
||||
return self._state == "answer" and not self._show_both_sides
|
||||
|
||||
def _should_enable_next(self):
|
||||
def _should_enable_next(self) -> bool:
|
||||
return self._state == "question"
|
||||
|
||||
def _on_close(self):
|
||||
def _on_close(self) -> None:
|
||||
super()._on_close()
|
||||
self._prev = None
|
||||
self._next = None
|
||||
@ -317,15 +320,15 @@ class BrowserPreviewer(MultiCardPreviewer):
|
||||
lambda: self._parent._moveCur(QAbstractItemView.MoveUp)
|
||||
)
|
||||
|
||||
def _on_next_card(self):
|
||||
def _on_next_card(self) -> None:
|
||||
self._parent.editor.saveNow(
|
||||
lambda: self._parent._moveCur(QAbstractItemView.MoveDown)
|
||||
)
|
||||
|
||||
def _should_enable_prev(self):
|
||||
def _should_enable_prev(self) -> bool:
|
||||
return super()._should_enable_prev() or self._parent.currentRow() > 0
|
||||
|
||||
def _should_enable_next(self):
|
||||
def _should_enable_next(self) -> bool:
|
||||
return (
|
||||
super()._should_enable_next()
|
||||
or self._parent.currentRow() < self._parent.model.rowCount(None) - 1
|
||||
|
@ -119,11 +119,11 @@ class AnkiRestart(SystemExit):
|
||||
|
||||
|
||||
class ProfileManager:
|
||||
def __init__(self, base=None):
|
||||
def __init__(self, base: Optional[str] = None) -> None:
|
||||
## Settings which should be forgotten each Anki restart
|
||||
self.session = {}
|
||||
self.name = None
|
||||
self.db = None
|
||||
self.session: Dict[str, Any] = {}
|
||||
self.name: Optional[str] = None
|
||||
self.db: Optional[DB] = None
|
||||
self.profile: Optional[Dict] = None
|
||||
# instantiate base folder
|
||||
self.base: str
|
||||
@ -170,7 +170,7 @@ class ProfileManager:
|
||||
return p
|
||||
return os.path.expanduser("~/Documents/Anki")
|
||||
|
||||
def maybeMigrateFolder(self):
|
||||
def maybeMigrateFolder(self) -> None:
|
||||
newBase = self.base
|
||||
oldBase = self._oldFolderLocation()
|
||||
|
||||
@ -206,7 +206,7 @@ class ProfileManager:
|
||||
confirmation.setText(
|
||||
"Anki needs to move its data folder from Documents/Anki to a new location. Proceed?"
|
||||
)
|
||||
retval = confirmation.exec()
|
||||
retval = confirmation.exec_()
|
||||
|
||||
if retval == QMessageBox.Ok:
|
||||
progress = QMessageBox()
|
||||
@ -228,7 +228,7 @@ class ProfileManager:
|
||||
completion.setWindowTitle(window_title)
|
||||
completion.setText("Migration complete. Please start Anki again.")
|
||||
completion.show()
|
||||
completion.exec()
|
||||
completion.exec_()
|
||||
else:
|
||||
diag = QMessageBox()
|
||||
diag.setIcon(QMessageBox.Warning)
|
||||
@ -239,7 +239,7 @@ class ProfileManager:
|
||||
"Migration aborted. If you would like to keep the old folder location, please "
|
||||
"see the Startup Options section of the manual. Anki will now quit."
|
||||
)
|
||||
diag.exec()
|
||||
diag.exec_()
|
||||
|
||||
raise AnkiRestart(exitcode=0)
|
||||
|
||||
@ -424,7 +424,7 @@ class ProfileManager:
|
||||
os.makedirs(path)
|
||||
return path
|
||||
|
||||
def _setBaseFolder(self, cmdlineBase: None) -> None:
|
||||
def _setBaseFolder(self, cmdlineBase: Optional[str]) -> None:
|
||||
if cmdlineBase:
|
||||
self.base = os.path.abspath(cmdlineBase)
|
||||
elif os.environ.get("ANKI_BASE"):
|
||||
|
@ -4,7 +4,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
from typing import Optional
|
||||
from typing import Callable, Optional
|
||||
|
||||
import aqt.forms
|
||||
from aqt.qt import *
|
||||
@ -15,13 +15,13 @@ from aqt.utils import TR, disable_help_button, tr
|
||||
|
||||
|
||||
class ProgressManager:
|
||||
def __init__(self, mw):
|
||||
def __init__(self, mw: aqt.AnkiQt) -> None:
|
||||
self.mw = mw
|
||||
self.app = QApplication.instance()
|
||||
self.inDB = False
|
||||
self.blockUpdates = False
|
||||
self._show_timer: Optional[QTimer] = None
|
||||
self._win = None
|
||||
self._win: Optional[ProgressDialog] = None
|
||||
self._levels = 0
|
||||
|
||||
# Safer timers
|
||||
@ -29,7 +29,9 @@ class ProgressManager:
|
||||
# A custom timer which avoids firing while a progress dialog is active
|
||||
# (likely due to some long-running DB operation)
|
||||
|
||||
def timer(self, ms, func, repeat, requiresCollection=True):
|
||||
def timer(
|
||||
self, ms: int, func: Callable, repeat: bool, requiresCollection: bool = True
|
||||
) -> QTimer:
|
||||
"""Create and start a standard Anki timer.
|
||||
|
||||
If the timer fires while a progress window is shown:
|
||||
@ -136,7 +138,7 @@ class ProgressManager:
|
||||
self._updating = False
|
||||
self._lastUpdate = time.time()
|
||||
|
||||
def finish(self):
|
||||
def finish(self) -> None:
|
||||
self._levels -= 1
|
||||
self._levels = max(0, self._levels)
|
||||
if self._levels == 0:
|
||||
@ -147,13 +149,13 @@ class ProgressManager:
|
||||
self._show_timer.stop()
|
||||
self._show_timer = None
|
||||
|
||||
def clear(self):
|
||||
def clear(self) -> None:
|
||||
"Restore the interface after an error."
|
||||
if self._levels:
|
||||
self._levels = 1
|
||||
self.finish()
|
||||
|
||||
def _maybeShow(self):
|
||||
def _maybeShow(self) -> None:
|
||||
if not self._levels:
|
||||
return
|
||||
if self._shown:
|
||||
@ -181,17 +183,17 @@ class ProgressManager:
|
||||
self._win = None
|
||||
self._shown = 0
|
||||
|
||||
def _setBusy(self):
|
||||
def _setBusy(self) -> None:
|
||||
self.mw.app.setOverrideCursor(QCursor(Qt.WaitCursor))
|
||||
|
||||
def _unsetBusy(self):
|
||||
def _unsetBusy(self) -> None:
|
||||
self.app.restoreOverrideCursor()
|
||||
|
||||
def busy(self):
|
||||
def busy(self) -> int:
|
||||
"True if processing."
|
||||
return self._levels
|
||||
|
||||
def _on_show_timer(self):
|
||||
def _on_show_timer(self) -> None:
|
||||
self._show_timer = None
|
||||
self._showWin()
|
||||
|
||||
@ -209,7 +211,7 @@ class ProgressManager:
|
||||
|
||||
|
||||
class ProgressDialog(QDialog):
|
||||
def __init__(self, parent):
|
||||
def __init__(self, parent: QWidget) -> None:
|
||||
QDialog.__init__(self, parent)
|
||||
disable_help_button(self)
|
||||
self.form = aqt.forms.progress.Ui_Dialog()
|
||||
@ -219,7 +221,7 @@ class ProgressDialog(QDialog):
|
||||
# required for smooth progress bars
|
||||
self.form.progressBar.setStyleSheet("QProgressBar::chunk { width: 1px; }")
|
||||
|
||||
def cancel(self):
|
||||
def cancel(self) -> None:
|
||||
self._closingDown = True
|
||||
self.hide()
|
||||
|
||||
|
@ -8,7 +8,7 @@ import html
|
||||
import json
|
||||
import re
|
||||
import unicodedata as ucd
|
||||
from typing import Callable, List, Optional, Tuple, Union
|
||||
from typing import Any, Callable, List, Optional, Tuple, Union
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
|
||||
@ -697,7 +697,7 @@ time = %(time)d;
|
||||
##########################################################################
|
||||
|
||||
# note the shortcuts listed here also need to be defined above
|
||||
def _contextMenu(self):
|
||||
def _contextMenu(self) -> List[Any]:
|
||||
currentFlag = self.card and self.card.userFlag()
|
||||
opts = [
|
||||
[
|
||||
|
@ -20,7 +20,7 @@ class ChangeTracker:
|
||||
def __init__(self, mw: AnkiQt):
|
||||
self.mw = mw
|
||||
|
||||
def mark_basic(self):
|
||||
def mark_basic(self) -> None:
|
||||
if self._changed == Change.NO_CHANGE:
|
||||
self._changed = Change.BASIC_CHANGE
|
||||
|
||||
|
@ -54,7 +54,7 @@ class NewDeckStats(QDialog):
|
||||
self.form.web.set_bridge_command(self._on_bridge_cmd, self)
|
||||
self.activateWindow()
|
||||
|
||||
def reject(self):
|
||||
def reject(self) -> None:
|
||||
self.form.web = None
|
||||
saveGeom(self, self.name)
|
||||
aqt.dialogs.markClosed("NewDeckStats")
|
||||
@ -98,14 +98,14 @@ class NewDeckStats(QDialog):
|
||||
|
||||
return False
|
||||
|
||||
def refresh(self):
|
||||
def refresh(self) -> None:
|
||||
self.form.web.load_ts_page("graphs")
|
||||
|
||||
|
||||
class DeckStats(QDialog):
|
||||
"""Legacy deck stats, used by some add-ons."""
|
||||
|
||||
def __init__(self, mw):
|
||||
def __init__(self, mw: aqt.main.AnkiQt) -> None:
|
||||
QDialog.__init__(self, mw, Qt.Window)
|
||||
mw.setupDialogGC(self)
|
||||
self.mw = mw
|
||||
@ -143,7 +143,7 @@ class DeckStats(QDialog):
|
||||
self.refresh()
|
||||
self.activateWindow()
|
||||
|
||||
def reject(self):
|
||||
def reject(self) -> None:
|
||||
self.form.web = None
|
||||
saveGeom(self, self.name)
|
||||
aqt.dialogs.markClosed("DeckStats")
|
||||
@ -173,15 +173,15 @@ class DeckStats(QDialog):
|
||||
self.form.web.page().printToPdf(path)
|
||||
tooltip(tr(TR.STATISTICS_SAVED))
|
||||
|
||||
def changePeriod(self, n):
|
||||
def changePeriod(self, n: int) -> None:
|
||||
self.period = n
|
||||
self.refresh()
|
||||
|
||||
def changeScope(self, type):
|
||||
def changeScope(self, type: str) -> None:
|
||||
self.wholeCollection = type == "collection"
|
||||
self.refresh()
|
||||
|
||||
def refresh(self):
|
||||
def refresh(self) -> None:
|
||||
self.mw.progress.start(parent=self)
|
||||
stats = self.mw.col.stats()
|
||||
stats.wholeCollection = self.wholeCollection
|
||||
|
@ -2,6 +2,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
from typing import Optional
|
||||
|
||||
import aqt
|
||||
from aqt import gui_hooks
|
||||
from aqt.qt import *
|
||||
@ -109,7 +111,7 @@ class StudyDeck(QDialog):
|
||||
return True
|
||||
return False
|
||||
|
||||
def redraw(self, filt, focus=None):
|
||||
def redraw(self, filt: str, focus: Optional[str] = None) -> None:
|
||||
self.filt = filt
|
||||
self.focus = focus
|
||||
self.names = [n for n in self.origNames if self._matches(n, filt)]
|
||||
@ -123,7 +125,7 @@ class StudyDeck(QDialog):
|
||||
l.setCurrentRow(idx)
|
||||
l.scrollToItem(l.item(idx), QAbstractItemView.PositionAtCenter)
|
||||
|
||||
def _matches(self, name, filt):
|
||||
def _matches(self, name: str, filt: str) -> bool:
|
||||
name = name.lower()
|
||||
filt = filt.lower()
|
||||
if not filt:
|
||||
|
@ -4,7 +4,9 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from typing import Iterable, List, Optional, Union
|
||||
|
||||
from anki.collection import Collection
|
||||
from aqt import gui_hooks
|
||||
from aqt.qt import *
|
||||
|
||||
@ -15,9 +17,9 @@ class TagEdit(QLineEdit):
|
||||
lostFocus = pyqtSignal()
|
||||
|
||||
# 0 = tags, 1 = decks
|
||||
def __init__(self, parent, type=0):
|
||||
def __init__(self, parent: QDialog, type: int = 0) -> None:
|
||||
QLineEdit.__init__(self, parent)
|
||||
self.col = None
|
||||
self.col: Optional[Collection] = None
|
||||
self.model = QStringListModel()
|
||||
self.type = type
|
||||
if type == 0:
|
||||
@ -28,19 +30,20 @@ class TagEdit(QLineEdit):
|
||||
self.completer.setCaseSensitivity(Qt.CaseInsensitive)
|
||||
self.setCompleter(self.completer)
|
||||
|
||||
def setCol(self, col):
|
||||
def setCol(self, col: Collection) -> None:
|
||||
"Set the current col, updating list of available tags."
|
||||
self.col = col
|
||||
l: Iterable[str]
|
||||
if self.type == 0:
|
||||
l = self.col.tags.all()
|
||||
else:
|
||||
l = (d.name for d in self.col.decks.all_names_and_ids())
|
||||
self.model.setStringList(l)
|
||||
|
||||
def focusInEvent(self, evt):
|
||||
def focusInEvent(self, evt: QFocusEvent) -> None:
|
||||
QLineEdit.focusInEvent(self, evt)
|
||||
|
||||
def keyPressEvent(self, evt):
|
||||
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():
|
||||
@ -85,7 +88,7 @@ class TagEdit(QLineEdit):
|
||||
self.showCompleter()
|
||||
gui_hooks.tag_editor_did_process_key(self, evt)
|
||||
|
||||
def showCompleter(self):
|
||||
def showCompleter(self) -> None:
|
||||
self.completer.setCompletionPrefix(self.text())
|
||||
self.completer.complete()
|
||||
|
||||
@ -94,20 +97,26 @@ class TagEdit(QLineEdit):
|
||||
self.lostFocus.emit() # type: ignore
|
||||
self.completer.popup().hide()
|
||||
|
||||
def hideCompleter(self):
|
||||
def hideCompleter(self) -> None:
|
||||
if sip.isdeleted(self.completer):
|
||||
return
|
||||
self.completer.popup().hide()
|
||||
|
||||
|
||||
class TagCompleter(QCompleter):
|
||||
def __init__(self, model, parent, edit, *args):
|
||||
def __init__(
|
||||
self,
|
||||
model: QStringListModel,
|
||||
parent: QWidget,
|
||||
edit: TagEdit,
|
||||
*args,
|
||||
) -> None:
|
||||
QCompleter.__init__(self, model, parent)
|
||||
self.tags = []
|
||||
self.tags: List[str] = []
|
||||
self.edit = edit
|
||||
self.cursor = None
|
||||
self.cursor: Optional[int] = None
|
||||
|
||||
def splitPath(self, tags):
|
||||
def splitPath(self, tags: str) -> List[str]:
|
||||
stripped_tags = tags.strip()
|
||||
stripped_tags = re.sub(" +", " ", stripped_tags)
|
||||
self.tags = self.edit.col.tags.split(stripped_tags)
|
||||
@ -119,7 +128,7 @@ class TagCompleter(QCompleter):
|
||||
self.cursor = stripped_tags.count(" ", 0, p)
|
||||
return [self.tags[self.cursor]]
|
||||
|
||||
def pathFromIndex(self, idx):
|
||||
def pathFromIndex(self, idx: QModelIndex) -> str:
|
||||
if self.cursor is None:
|
||||
return self.edit.text()
|
||||
ret = QCompleter.pathFromIndex(self, idx)
|
||||
|
@ -3,14 +3,17 @@
|
||||
from typing import List, Optional
|
||||
|
||||
import aqt
|
||||
from aqt.customstudy import CustomStudy
|
||||
from aqt.main import AnkiQt
|
||||
from aqt.qt import *
|
||||
from aqt.utils import disable_help_button, restoreGeom, saveGeom
|
||||
|
||||
|
||||
class TagLimit(QDialog):
|
||||
def __init__(self, mw, parent):
|
||||
def __init__(self, mw: AnkiQt, parent: CustomStudy) -> None:
|
||||
QDialog.__init__(self, parent, Qt.Window)
|
||||
self.tags: Union[str, List] = ""
|
||||
self.tags: str = ""
|
||||
self.tags_list: List[str] = []
|
||||
self.mw = mw
|
||||
self.parent: Optional[QWidget] = parent
|
||||
self.deck = self.parent.deck
|
||||
@ -29,7 +32,7 @@ class TagLimit(QDialog):
|
||||
restoreGeom(self, "tagLimit")
|
||||
self.exec_()
|
||||
|
||||
def rebuildTagList(self):
|
||||
def rebuildTagList(self) -> None:
|
||||
usertags = self.mw.col.tags.byDeck(self.deck["id"], True)
|
||||
yes = self.deck.get("activeTags", [])
|
||||
no = self.deck.get("inactiveTags", [])
|
||||
@ -42,10 +45,10 @@ class TagLimit(QDialog):
|
||||
groupedTags = []
|
||||
usertags.sort()
|
||||
groupedTags.append(usertags)
|
||||
self.tags = []
|
||||
self.tags_list = []
|
||||
for tags in groupedTags:
|
||||
for t in tags:
|
||||
self.tags.append(t)
|
||||
self.tags_list.append(t)
|
||||
item = QListWidgetItem(t.replace("_", " "))
|
||||
self.dialog.activeList.addItem(item)
|
||||
if t in yesHash:
|
||||
@ -69,7 +72,7 @@ class TagLimit(QDialog):
|
||||
self.tags = ""
|
||||
QDialog.reject(self)
|
||||
|
||||
def accept(self):
|
||||
def accept(self) -> None:
|
||||
self.hide()
|
||||
# gather yes/no tags
|
||||
yes = []
|
||||
@ -80,12 +83,12 @@ class TagLimit(QDialog):
|
||||
item = self.dialog.activeList.item(c)
|
||||
idx = self.dialog.activeList.indexFromItem(item)
|
||||
if self.dialog.activeList.selectionModel().isSelected(idx):
|
||||
yes.append(self.tags[c])
|
||||
yes.append(self.tags_list[c])
|
||||
# inactive
|
||||
item = self.dialog.inactiveList.item(c)
|
||||
idx = self.dialog.inactiveList.indexFromItem(item)
|
||||
if self.dialog.inactiveList.selectionModel().isSelected(idx):
|
||||
no.append(self.tags[c])
|
||||
no.append(self.tags_list[c])
|
||||
# save in the deck for future invocations
|
||||
self.deck["activeTags"] = yes
|
||||
self.deck["inactiveTags"] = no
|
||||
|
@ -78,7 +78,7 @@ class TaskManager(QObject):
|
||||
|
||||
self.run_in_background(task, wrapped_done)
|
||||
|
||||
def _on_closures_pending(self):
|
||||
def _on_closures_pending(self) -> None:
|
||||
"""Run any pending closures. This runs in the main thread."""
|
||||
with self._closures_lock:
|
||||
closures = self._closures
|
||||
|
@ -7,6 +7,7 @@ import requests
|
||||
|
||||
import aqt
|
||||
from anki.utils import platDesc, versionWithBuild
|
||||
from aqt.main import AnkiQt
|
||||
from aqt.qt import *
|
||||
from aqt.utils import TR, openLink, showText, tr
|
||||
|
||||
@ -17,7 +18,7 @@ class LatestVersionFinder(QThread):
|
||||
newMsg = pyqtSignal(dict)
|
||||
clockIsOff = pyqtSignal(float)
|
||||
|
||||
def __init__(self, main):
|
||||
def __init__(self, main: AnkiQt) -> None:
|
||||
QThread.__init__(self)
|
||||
self.main = main
|
||||
self.config = main.pm.meta
|
||||
|
Loading…
Reference in New Issue
Block a user