switch to new-style PyQt scoped enums and Qt6

The enum changes should work on PyQt 5.x, and are required in PyQt 6.x.
They are not supported by the PyQt5 typings however, so we need to run
our tests with PyQt6.
This commit is contained in:
Damien Elmes 2021-10-05 13:53:01 +10:00
parent b0272f0336
commit a7812dedc0
56 changed files with 526 additions and 385 deletions

View file

@ -1,6 +1,6 @@
[MASTER] [MASTER]
persistent = no persistent = no
extension-pkg-whitelist=PyQt5,PyQt6 extension-pkg-whitelist=PyQt6
ignore = forms,hooks_gen.py ignore = forms,hooks_gen.py
[TYPECHECK] [TYPECHECK]

View file

@ -45,21 +45,21 @@ py_test(
args = [ args = [
"aqt", "aqt",
"$(location mypy.ini)", "$(location mypy.ini)",
"$(location @pyqt5//:__init__.py)", "$(location @pyqt6//:__init__.py)",
"$(location //pip/stubs:extendsitepkgs)", "$(location //pip/stubs:extendsitepkgs)",
], ],
data = [ data = [
"mypy.ini", "mypy.ini",
"//pip/stubs", "//pip/stubs",
"//pip/stubs:extendsitepkgs", "//pip/stubs:extendsitepkgs",
"@pyqt5//:__init__.py", "@pyqt6//:__init__.py",
], ],
env = {"EXTRA_SITE_PACKAGES": "$(location //pip/stubs)"}, env = {"EXTRA_SITE_PACKAGES": "$(location //pip/stubs)"},
main = "tests/run_mypy.py", main = "tests/run_mypy.py",
deps = [ deps = [
"//pylib/anki", "//pylib/anki",
"//qt/aqt:aqt_without_data", "//qt/aqt:aqt_without_data",
"@pyqt5//:pkg", "@pyqt6//:pkg",
requirement("mypy"), requirement("mypy"),
], ],
) )

View file

@ -50,7 +50,7 @@ aqt_deps = [
requirement("waitress"), requirement("waitress"),
requirement("send2trash"), requirement("send2trash"),
requirement("jsonschema"), requirement("jsonschema"),
"@pyqt5//:pkg", "@pyqt6//:pkg",
] + select({ ] + select({
"@bazel_tools//src/conditions:host_windows": [ "@bazel_tools//src/conditions:host_windows": [
requirement("psutil"), requirement("psutil"),

View file

@ -99,8 +99,10 @@ class DialogManager:
def open(self, name: str, *args: Any, **kwargs: Any) -> Any: def open(self, name: str, *args: Any, **kwargs: Any) -> Any:
(creator, instance) = self._dialogs[name] (creator, instance) = self._dialogs[name]
if instance: if instance:
if instance.windowState() & Qt.WindowMinimized: if instance.windowState() & Qt.WindowState.WindowMinimized:
instance.setWindowState(instance.windowState() & ~Qt.WindowMinimized) instance.setWindowState(
instance.windowState() & ~Qt.WindowState.WindowMinimized
)
instance.activateWindow() instance.activateWindow()
instance.raise_() instance.raise_()
if hasattr(instance, "reopen"): if hasattr(instance, "reopen"):
@ -224,9 +226,9 @@ def setupLangAndBackend(
# switch direction for RTL languages # switch direction for RTL languages
if anki.lang.is_rtl(lang): if anki.lang.is_rtl(lang):
app.setLayoutDirection(Qt.RightToLeft) app.setLayoutDirection(Qt.LayoutDirection.RightToLeft)
else: else:
app.setLayoutDirection(Qt.LeftToRight) app.setLayoutDirection(Qt.LayoutDirection.LeftToRight)
# load qt translations # load qt translations
_qtrans = QTranslator() _qtrans = QTranslator()
@ -238,7 +240,10 @@ def setupLangAndBackend(
os.path.join(aqt_data_folder(), "..", "qt_translations") os.path.join(aqt_data_folder(), "..", "qt_translations")
) )
else: else:
qt_dir = QLibraryInfo.location(QLibraryInfo.TranslationsPath) if qtmajor == 5:
qt_dir = QLibraryInfo.location(QLibraryInfo.TranslationsPath) # type: ignore
else:
qt_dir = QLibraryInfo.path(QLibraryInfo.LibraryPath.TranslationsPath)
qt_lang = lang.replace("-", "_") qt_lang = lang.replace("-", "_")
if _qtrans.load(f"qtbase_{qt_lang}", qt_dir): if _qtrans.load(f"qtbase_{qt_lang}", qt_dir):
app.installTranslator(_qtrans) app.installTranslator(_qtrans)
@ -285,7 +290,7 @@ class AnkiApp(QApplication):
def sendMsg(self, txt: str) -> bool: def sendMsg(self, txt: str) -> bool:
sock = QLocalSocket(self) sock = QLocalSocket(self)
sock.connectToServer(self.KEY, QIODevice.WriteOnly) sock.connectToServer(self.KEY, QIODevice.OpenModeFlag.WriteOnly)
if not sock.waitForConnected(self.TMOUT): if not sock.waitForConnected(self.TMOUT):
# first instance or previous instance dead # first instance or previous instance dead
return False return False
@ -315,7 +320,7 @@ class AnkiApp(QApplication):
################################################## ##################################################
def event(self, evt: QEvent) -> bool: def event(self, evt: QEvent) -> bool:
if evt.type() == QEvent.FileOpen: if evt.type() == QEvent.Type.FileOpen:
self.appMsg.emit(evt.file() or "raise") # type: ignore self.appMsg.emit(evt.file() or "raise") # type: ignore
return True return True
return QApplication.event(self, evt) return QApplication.event(self, evt)
@ -360,17 +365,17 @@ def setupGL(pm: aqt.profiles.ProfileManager) -> None:
# catch opengl errors # catch opengl errors
def msgHandler(category: Any, ctx: Any, msg: Any) -> None: def msgHandler(category: Any, ctx: Any, msg: Any) -> None:
if category == QtDebugMsg: if category == QtMsgType.QtDebugMsg:
category = "debug" category = "debug"
elif category == QtInfoMsg: elif category == QtMsgType.QtInfoMsg:
category = "info" category = "info"
elif category == QtWarningMsg: elif category == QtMsgType.QtWarningMsg:
category = "warning" category = "warning"
elif category == QtCriticalMsg: elif category == QtMsgType.QtCriticalMsg:
category = "critical" category = "critical"
elif category == QtDebugMsg: elif category == QtMsgType.QtDebugMsg:
category = "debug" category = "debug"
elif category == QtFatalMsg: elif category == QtMsgType.QtFatalMsg:
category = "fatal" category = "fatal"
else: else:
category = "unknown" category = "unknown"
@ -405,7 +410,7 @@ def setupGL(pm: aqt.profiles.ProfileManager) -> None:
if isWin: if isWin:
os.environ["QT_OPENGL"] = driver.value os.environ["QT_OPENGL"] = driver.value
elif isMac: elif isMac:
QCoreApplication.setAttribute(Qt.AA_UseSoftwareOpenGL) QCoreApplication.setAttribute(Qt.ApplicationAttribute.AA_UseSoftwareOpenGL)
elif isLin: elif isLin:
os.environ["QT_XCB_FORCE_SOFTWARE_OPENGL"] = "1" os.environ["QT_XCB_FORCE_SOFTWARE_OPENGL"] = "1"
@ -499,15 +504,15 @@ def _run(argv: Optional[list[str]] = None, exec: bool = True) -> Optional[AnkiAp
os.environ["QT_SCALE_FACTOR"] = str(pm.uiScale()) os.environ["QT_SCALE_FACTOR"] = str(pm.uiScale())
# opt in to full hidpi support? # opt in to full hidpi support?
if not os.environ.get("ANKI_NOHIGHDPI"): if not os.environ.get("ANKI_NOHIGHDPI") and qtmajor == 5:
QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling) QCoreApplication.setAttribute(Qt.ApplicationAttribute.AA_EnableHighDpiScaling) # type: ignore
QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps) QCoreApplication.setAttribute(Qt.ApplicationAttribute.AA_UseHighDpiPixmaps) # type: ignore
os.environ["QT_ENABLE_HIGHDPI_SCALING"] = "1" os.environ["QT_ENABLE_HIGHDPI_SCALING"] = "1"
os.environ["QT_SCALE_FACTOR_ROUNDING_POLICY"] = "PassThrough" os.environ["QT_SCALE_FACTOR_ROUNDING_POLICY"] = "PassThrough"
# Opt into software rendering. Useful for buggy systems. # Opt into software rendering. Useful for buggy systems.
if os.environ.get("ANKI_SOFTWAREOPENGL"): if os.environ.get("ANKI_SOFTWAREOPENGL"):
QCoreApplication.setAttribute(Qt.AA_UseSoftwareOpenGL) QCoreApplication.setAttribute(Qt.ApplicationAttribute.AA_UseSoftwareOpenGL)
if ( if (
isWin isWin
@ -535,11 +540,13 @@ def _run(argv: Optional[list[str]] = None, exec: bool = True) -> Optional[AnkiAp
# disable icons on mac; this must be done before window created # disable icons on mac; this must be done before window created
if isMac: if isMac:
app.setAttribute(Qt.AA_DontShowIconsInMenus) app.setAttribute(Qt.ApplicationAttribute.AA_DontShowIconsInMenus)
# disable help button in title bar on qt versions that support it # disable help button in title bar on qt versions that support it
if isWin and qtminor >= 10: if isWin and qtmajor == 5 and qtminor >= 10:
QApplication.setAttribute(Qt.AA_DisableWindowContextHelpButton) QApplication.setAttribute(
QApplication.Attribute.AA_DisableWindowContextHelpButton # type: ignore
)
# proxy configured? # proxy configured?
from urllib.request import getproxies, proxy_bypass from urllib.request import getproxies, proxy_bypass
@ -559,7 +566,7 @@ def _run(argv: Optional[list[str]] = None, exec: bool = True) -> Optional[AnkiAp
if disable_proxies: if disable_proxies:
print("webview proxy use disabled") print("webview proxy use disabled")
proxy = QNetworkProxy() proxy = QNetworkProxy()
proxy.setType(QNetworkProxy.NoProxy) proxy.setType(QNetworkProxy.ProxyType.NoProxy)
QNetworkProxy.setApplicationProxy(proxy) QNetworkProxy.setApplicationProxy(proxy)
# we must have a usable temp dir # we must have a usable temp dir

View file

@ -88,8 +88,8 @@ def show(mw: aqt.AnkiQt) -> QDialog:
btn = QPushButton(tr.about_copy_debug_info()) btn = QPushButton(tr.about_copy_debug_info())
qconnect(btn.clicked, onCopy) qconnect(btn.clicked, onCopy)
abt.buttonBox.addButton(btn, QDialogButtonBox.ActionRole) abt.buttonBox.addButton(btn, QDialogButtonBox.ButtonRole.ActionRole)
abt.buttonBox.button(QDialogButtonBox.Ok).setFocus() abt.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setFocus()
# WebView contents # WebView contents
###################################################################### ######################################################################

View file

@ -35,7 +35,7 @@ from aqt.utils import (
class AddCards(QDialog): class AddCards(QDialog):
def __init__(self, mw: AnkiQt) -> None: def __init__(self, mw: AnkiQt) -> None:
QDialog.__init__(self, None, Qt.Window) QDialog.__init__(self, None, Qt.WindowType.Window)
mw.garbage_collect_on_dialog_finish(self) mw.garbage_collect_on_dialog_finish(self)
self.mw = mw self.mw = mw
self.col = mw.col self.col = mw.col
@ -85,7 +85,7 @@ class AddCards(QDialog):
def setupButtons(self) -> None: def setupButtons(self) -> None:
bb = self.form.buttonBox bb = self.form.buttonBox
ar = QDialogButtonBox.ActionRole ar = QDialogButtonBox.ButtonRole.ActionRole
# add # add
self.addButton = bb.addButton(tr.actions_add(), ar) self.addButton = bb.addButton(tr.actions_add(), ar)
qconnect(self.addButton.clicked, self.add_current_note) qconnect(self.addButton.clicked, self.add_current_note)
@ -97,11 +97,11 @@ class AddCards(QDialog):
# close # close
self.closeButton = QPushButton(tr.actions_close()) self.closeButton = QPushButton(tr.actions_close())
self.closeButton.setAutoDefault(False) self.closeButton.setAutoDefault(False)
bb.addButton(self.closeButton, QDialogButtonBox.RejectRole) bb.addButton(self.closeButton, QDialogButtonBox.ButtonRole.RejectRole)
# help # help
self.helpButton = QPushButton(tr.actions_help(), clicked=self.helpRequested) # type: ignore self.helpButton = QPushButton(tr.actions_help(), clicked=self.helpRequested) # type: ignore
self.helpButton.setAutoDefault(False) self.helpButton.setAutoDefault(False)
bb.addButton(self.helpButton, QDialogButtonBox.HelpRole) bb.addButton(self.helpButton, QDialogButtonBox.ButtonRole.HelpRole)
# history # history
b = bb.addButton(f"{tr.adding_history()} {downArrow()}", ar) b = bb.addButton(f"{tr.adding_history()} {downArrow()}", ar)
if isMac: if isMac:
@ -266,7 +266,10 @@ class AddCards(QDialog):
def keyPressEvent(self, evt: QKeyEvent) -> None: def keyPressEvent(self, evt: QKeyEvent) -> None:
"Show answer on RET or register answer." "Show answer on RET or register answer."
if evt.key() in (Qt.Key_Enter, Qt.Key_Return) and self.editor.tags.hasFocus(): if (
evt.key() in (Qt.Key.Key_Enter, Qt.Key.Key_Return)
and self.editor.tags.hasFocus()
):
evt.accept() evt.accept()
return return
return QDialog.keyPressEvent(self, evt) return QDialog.keyPressEvent(self, evt)

View file

@ -804,7 +804,7 @@ class AddonsDialog(QDialog):
name = self.name_for_addon_list(addon) name = self.name_for_addon_list(addon)
item = QListWidgetItem(name, addonList) item = QListWidgetItem(name, addonList)
if self.should_grey(addon): if self.should_grey(addon):
item.setForeground(Qt.gray) item.setForeground(Qt.GlobalColor.gray)
if addon.dir_name in selected: if addon.dir_name in selected:
item.setSelected(True) item.setSelected(True)
@ -947,7 +947,7 @@ class GetAddons(QDialog):
self.form = aqt.forms.getaddons.Ui_Dialog() self.form = aqt.forms.getaddons.Ui_Dialog()
self.form.setupUi(self) self.form.setupUi(self)
b = self.form.buttonBox.addButton( b = self.form.buttonBox.addButton(
tr.addons_browse_addons(), QDialogButtonBox.ActionRole tr.addons_browse_addons(), QDialogButtonBox.ButtonRole.ActionRole
) )
qconnect(b.clicked, self.onBrowse) qconnect(b.clicked, self.onBrowse)
disable_help_button(self) disable_help_button(self)
@ -1183,7 +1183,7 @@ class ChooseAddonsToUpdateList(QListWidget):
) )
self.ignore_check_evt = False self.ignore_check_evt = False
self.setup() self.setup()
self.setContextMenuPolicy(Qt.CustomContextMenu) self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
qconnect(self.itemClicked, self.on_click) qconnect(self.itemClicked, self.on_click)
qconnect(self.itemChanged, self.on_check) qconnect(self.itemChanged, self.on_check)
qconnect(self.itemDoubleClicked, self.on_double_click) qconnect(self.itemDoubleClicked, self.on_double_click)
@ -1191,7 +1191,9 @@ class ChooseAddonsToUpdateList(QListWidget):
def setup(self) -> None: def setup(self) -> None:
header_item = QListWidgetItem(tr.addons_choose_update_update_all(), self) header_item = QListWidgetItem(tr.addons_choose_update_update_all(), self)
header_item.setFlags(Qt.ItemFlag(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)) header_item.setFlags(
Qt.ItemFlag(Qt.ItemFlag.ItemIsUserCheckable | Qt.ItemFlag.ItemIsEnabled)
)
self.header_item = header_item self.header_item = header_item
for update_info in self.updated_addons: for update_info in self.updated_addons:
addon_id = update_info.id addon_id = update_info.id
@ -1204,22 +1206,22 @@ class ChooseAddonsToUpdateList(QListWidget):
addon_label = f"{update_time:%Y-%m-%d} {addon_name}" addon_label = f"{update_time:%Y-%m-%d} {addon_name}"
item = QListWidgetItem(addon_label, self) item = QListWidgetItem(addon_label, self)
# Not user checkable because it overlaps with itemClicked signal # Not user checkable because it overlaps with itemClicked signal
item.setFlags(Qt.ItemFlag(Qt.ItemIsEnabled)) item.setFlags(Qt.ItemFlag(Qt.ItemFlag.ItemIsEnabled))
if update_enabled: if update_enabled:
item.setCheckState(Qt.Checked) item.setCheckState(Qt.CheckState.Checked)
else: else:
item.setCheckState(Qt.Unchecked) item.setCheckState(Qt.CheckState.Unchecked)
item.setData(self.ADDON_ID_ROLE, addon_id) item.setData(self.ADDON_ID_ROLE, addon_id)
self.refresh_header_check_state() self.refresh_header_check_state()
def bool_to_check(self, check_bool: bool) -> Qt.CheckState: def bool_to_check(self, check_bool: bool) -> Qt.CheckState:
if check_bool: if check_bool:
return Qt.Checked return Qt.CheckState.Checked
else: else:
return Qt.Unchecked return Qt.CheckState.Unchecked
def checked(self, item: QListWidgetItem) -> bool: def checked(self, item: QListWidgetItem) -> bool:
return item.checkState() == Qt.Checked return item.checkState() == Qt.CheckState.Checked
def on_click(self, item: QListWidgetItem) -> None: def on_click(self, item: QListWidgetItem) -> None:
if item == self.header_item: if item == self.header_item:
@ -1262,9 +1264,9 @@ class ChooseAddonsToUpdateList(QListWidget):
for i in range(1, self.count()): for i in range(1, self.count()):
item = self.item(i) item = self.item(i)
if not self.checked(item): if not self.checked(item):
self.check_item(self.header_item, Qt.Unchecked) self.check_item(self.header_item, Qt.CheckState.Unchecked)
return return
self.check_item(self.header_item, Qt.Checked) self.check_item(self.header_item, Qt.CheckState.Checked)
def get_selected_addon_ids(self) -> list[int]: def get_selected_addon_ids(self) -> list[int]:
addon_ids = [] addon_ids = []
@ -1290,7 +1292,7 @@ class ChooseAddonsToUpdateDialog(QDialog):
) -> None: ) -> None:
QDialog.__init__(self, parent) QDialog.__init__(self, parent)
self.setWindowTitle(tr.addons_choose_update_window_title()) self.setWindowTitle(tr.addons_choose_update_window_title())
self.setWindowModality(Qt.WindowModal) self.setWindowModality(Qt.WindowModality.WindowModal)
self.mgr = mgr self.mgr = mgr
self.updated_addons = updated_addons self.updated_addons = updated_addons
self.setup() self.setup()
@ -1306,9 +1308,14 @@ class ChooseAddonsToUpdateDialog(QDialog):
layout.addWidget(addons_list_widget) layout.addWidget(addons_list_widget)
self.addons_list_widget = addons_list_widget self.addons_list_widget = addons_list_widget
button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) # type: ignore button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) # type: ignore
qconnect(button_box.button(QDialogButtonBox.Ok).clicked, self.accept) qconnect(
qconnect(button_box.button(QDialogButtonBox.Cancel).clicked, self.reject) button_box.button(QDialogButtonBox.StandardButton.Ok).clicked, self.accept
)
qconnect(
button_box.button(QDialogButtonBox.StandardButton.Cancel).clicked,
self.reject,
)
layout.addWidget(button_box) layout.addWidget(button_box)
self.setLayout(layout) self.setLayout(layout)
@ -1317,7 +1324,7 @@ class ChooseAddonsToUpdateDialog(QDialog):
ret = self.exec() ret = self.exec()
saveGeom(self, "addonsChooseUpdate") saveGeom(self, "addonsChooseUpdate")
self.addons_list_widget.save_check_state() self.addons_list_widget.save_check_state()
if ret == QDialog.Accepted: if ret == QDialog.DialogCode.Accepted:
return self.addons_list_widget.get_selected_addon_ids() return self.addons_list_widget.get_selected_addon_ids()
else: else:
return [] return []
@ -1475,7 +1482,9 @@ class ConfigEditor(QDialog):
self.mgr = dlg.mgr self.mgr = dlg.mgr
self.form = aqt.forms.addonconf.Ui_Dialog() self.form = aqt.forms.addonconf.Ui_Dialog()
self.form.setupUi(self) self.form.setupUi(self)
restore = self.form.buttonBox.button(QDialogButtonBox.RestoreDefaults) restore = self.form.buttonBox.button(
QDialogButtonBox.StandardButton.RestoreDefaults
)
qconnect(restore.clicked, self.onRestoreDefaults) qconnect(restore.clicked, self.onRestoreDefaults)
self.setupFonts() self.setupFonts()
self.updateHelp() self.updateHelp()
@ -1498,7 +1507,7 @@ class ConfigEditor(QDialog):
tooltip(tr.addons_restored_defaults(), parent=self) tooltip(tr.addons_restored_defaults(), parent=self)
def setupFonts(self) -> None: def setupFonts(self) -> None:
font_mono = QFontDatabase.systemFont(QFontDatabase.FixedFont) font_mono = QFontDatabase.systemFont(QFontDatabase.SystemFont.FixedFont)
font_mono.setPointSize(font_mono.pointSize() + 1) font_mono.setPointSize(font_mono.pointSize() + 1)
self.form.editor.setFont(font_mono) self.form.editor.setFont(font_mono)
@ -1600,9 +1609,12 @@ def installAddonPackages(
parent=parent, parent=parent,
title=tr.addons_install_anki_addon(), title=tr.addons_install_anki_addon(),
type="warning", type="warning",
customBtns=[QMessageBox.No, QMessageBox.Yes], customBtns=[
QMessageBox.StandardButton.No,
QMessageBox.StandardButton.Yes,
],
) )
== QMessageBox.Yes == QMessageBox.StandardButton.Yes
): ):
return False return False

View file

@ -104,7 +104,7 @@ class Browser(QMainWindow):
search -- set and perform search; caller must ensure validity search -- set and perform search; caller must ensure validity
""" """
QMainWindow.__init__(self, None, Qt.Window) QMainWindow.__init__(self, None, Qt.WindowType.Window)
self.mw = mw self.mw = mw
self.col = self.mw.col self.col = self.mw.col
self.lastFilter = "" self.lastFilter = ""
@ -255,7 +255,7 @@ class Browser(QMainWindow):
onsuccess() onsuccess()
def keyPressEvent(self, evt: QKeyEvent) -> None: def keyPressEvent(self, evt: QKeyEvent) -> None:
if evt.key() == Qt.Key_Escape: if evt.key() == Qt.Key.Key_Escape:
self.close() self.close()
else: else:
super().keyPressEvent(evt) super().keyPressEvent(evt)
@ -490,9 +490,9 @@ class Browser(QMainWindow):
def setupSidebar(self) -> None: def setupSidebar(self) -> None:
dw = self.sidebarDockWidget = QDockWidget(tr.browsing_sidebar(), self) dw = self.sidebarDockWidget = QDockWidget(tr.browsing_sidebar(), self)
dw.setFeatures(QDockWidget.NoDockWidgetFeatures) dw.setFeatures(QDockWidget.DockWidgetFeature.NoDockWidgetFeatures)
dw.setObjectName("Sidebar") dw.setObjectName("Sidebar")
dw.setAllowedAreas(Qt.LeftDockWidgetArea) dw.setAllowedAreas(Qt.DockWidgetArea.LeftDockWidgetArea)
self.sidebar = SidebarTreeView(self) self.sidebar = SidebarTreeView(self)
self.sidebarTree = self.sidebar # legacy alias self.sidebarTree = self.sidebar # legacy alias
@ -513,7 +513,7 @@ class Browser(QMainWindow):
self.sidebarDockWidget.setFloating(False) self.sidebarDockWidget.setFloating(False)
self.sidebarDockWidget.setTitleBarWidget(QWidget()) self.sidebarDockWidget.setTitleBarWidget(QWidget())
self.addDockWidget(Qt.LeftDockWidgetArea, dw) self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, dw)
# schedule sidebar to refresh after browser window has loaded, so the # schedule sidebar to refresh after browser window has loaded, so the
# UI is more responsive # UI is more responsive

View file

@ -28,7 +28,7 @@ class CardInfoDialog(QDialog):
self.show() self.show()
def _setup_ui(self, card_id: CardId) -> None: def _setup_ui(self, card_id: CardId) -> None:
self.setWindowModality(Qt.ApplicationModal) self.setWindowModality(Qt.WindowModality.ApplicationModal)
self.mw.garbage_collect_on_dialog_finish(self) self.mw.garbage_collect_on_dialog_finish(self)
disable_help_button(self) disable_help_button(self)
restoreGeom(self, self.GEOMETRY_KEY) restoreGeom(self, self.GEOMETRY_KEY)
@ -40,7 +40,7 @@ class CardInfoDialog(QDialog):
layout = QVBoxLayout() layout = QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0) layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(self.web) layout.addWidget(self.web)
buttons = QDialogButtonBox(QDialogButtonBox.Close) buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Close)
buttons.setContentsMargins(10, 0, 10, 10) buttons.setContentsMargins(10, 0, 10, 10)
layout.addWidget(buttons) layout.addWidget(buttons)
qconnect(buttons.rejected, self.reject) qconnect(buttons.rejected, self.reject)

View file

@ -73,16 +73,18 @@ class FindAndReplaceDialog(QDialog):
disable_help_button(self) disable_help_button(self)
self.form = aqt.forms.findreplace.Ui_Dialog() self.form = aqt.forms.findreplace.Ui_Dialog()
self.form.setupUi(self) self.form.setupUi(self)
self.setWindowModality(Qt.WindowModal) self.setWindowModality(Qt.WindowModality.WindowModal)
self._find_history = restore_combo_history( self._find_history = restore_combo_history(
self.form.find, self.COMBO_NAME + "Find" self.form.find, self.COMBO_NAME + "Find"
) )
self.form.find.completer().setCaseSensitivity(Qt.CaseSensitive) self.form.find.completer().setCaseSensitivity(Qt.CaseSensitivity.CaseSensitive)
self._replace_history = restore_combo_history( self._replace_history = restore_combo_history(
self.form.replace, self.COMBO_NAME + "Replace" self.form.replace, self.COMBO_NAME + "Replace"
) )
self.form.replace.completer().setCaseSensitivity(Qt.CaseSensitive) self.form.replace.completer().setCaseSensitivity(
Qt.CaseSensitivity.CaseSensitive
)
if not self.note_ids: if not self.note_ids:
# no selected notes to affect # no selected notes to affect

View file

@ -71,7 +71,7 @@ class FindDuplicatesDialog(QDialog):
).run_in_background() ).run_in_background()
search = form.buttonBox.addButton( search = form.buttonBox.addButton(
tr.actions_search(), QDialogButtonBox.ActionRole tr.actions_search(), QDialogButtonBox.ButtonRole.ActionRole
) )
qconnect(search.clicked, on_click) qconnect(search.clicked, on_click)
self.show() self.show()
@ -80,7 +80,7 @@ class FindDuplicatesDialog(QDialog):
self._dupes = dupes self._dupes = dupes
if not self._dupesButton: if not self._dupesButton:
self._dupesButton = b = self.form.buttonBox.addButton( self._dupesButton = b = self.form.buttonBox.addButton(
tr.browsing_tag_duplicates(), QDialogButtonBox.ActionRole tr.browsing_tag_duplicates(), QDialogButtonBox.ButtonRole.ActionRole
) )
qconnect(b.clicked, self._tag_duplicates) qconnect(b.clicked, self._tag_duplicates)
text = "" text = ""

View file

@ -46,14 +46,14 @@ class Previewer(QDialog):
def __init__( def __init__(
self, parent: QWidget, mw: AnkiQt, on_close: Callable[[], None] self, parent: QWidget, mw: AnkiQt, on_close: Callable[[], None]
) -> None: ) -> None:
super().__init__(None, Qt.Window) super().__init__(None, Qt.WindowType.Window)
mw.garbage_collect_on_dialog_finish(self) mw.garbage_collect_on_dialog_finish(self)
self._open = True self._open = True
self._parent = parent self._parent = parent
self._close_callback = on_close self._close_callback = on_close
self.mw = mw self.mw = mw
icon = QIcon() icon = QIcon()
icon.addPixmap(QPixmap("icons:anki.png"), QIcon.Normal, QIcon.Off) icon.addPixmap(QPixmap("icons:anki.png"), QIcon.Mode.Normal, QIcon.State.Off)
disable_help_button(self) disable_help_button(self)
self.setWindowIcon(icon) self.setWindowIcon(icon)
@ -86,7 +86,7 @@ class Previewer(QDialog):
self.bbox = QDialogButtonBox() self.bbox = QDialogButtonBox()
self._replay = self.bbox.addButton( self._replay = self.bbox.addButton(
tr.actions_replay_audio(), QDialogButtonBox.ActionRole tr.actions_replay_audio(), QDialogButtonBox.ButtonRole.ActionRole
) )
self._replay.setAutoDefault(False) self._replay.setAutoDefault(False)
self._replay.setShortcut(QKeySequence("R")) self._replay.setShortcut(QKeySequence("R"))
@ -96,7 +96,7 @@ class Previewer(QDialog):
both_sides_button = QCheckBox(tr.qt_misc_back_side_only()) both_sides_button = QCheckBox(tr.qt_misc_back_side_only())
both_sides_button.setShortcut(QKeySequence("B")) both_sides_button.setShortcut(QKeySequence("B"))
both_sides_button.setToolTip(tr.actions_shortcut_key(val="B")) both_sides_button.setToolTip(tr.actions_shortcut_key(val="B"))
self.bbox.addButton(both_sides_button, QDialogButtonBox.ActionRole) self.bbox.addButton(both_sides_button, QDialogButtonBox.ButtonRole.ActionRole)
self._show_both_sides = self.mw.col.get_config_bool( self._show_both_sides = self.mw.col.get_config_bool(
Config.Bool.PREVIEW_BOTH_SIDES Config.Bool.PREVIEW_BOTH_SIDES
) )
@ -266,12 +266,12 @@ class MultiCardPreviewer(Previewer):
def _create_gui(self) -> None: def _create_gui(self) -> None:
super()._create_gui() super()._create_gui()
self._prev = self.bbox.addButton("<", QDialogButtonBox.ActionRole) self._prev = self.bbox.addButton("<", QDialogButtonBox.ButtonRole.ActionRole)
self._prev.setAutoDefault(False) self._prev.setAutoDefault(False)
self._prev.setShortcut(QKeySequence("Left")) self._prev.setShortcut(QKeySequence("Left"))
self._prev.setToolTip(tr.qt_misc_shortcut_key_left_arrow()) self._prev.setToolTip(tr.qt_misc_shortcut_key_left_arrow())
self._next = self.bbox.addButton(">", QDialogButtonBox.ActionRole) self._next = self.bbox.addButton(">", QDialogButtonBox.ButtonRole.ActionRole)
self._next.setAutoDefault(True) self._next.setAutoDefault(True)
self._next.setShortcut(QKeySequence("Right")) self._next.setShortcut(QKeySequence("Right"))
self._next.setToolTip(tr.qt_misc_shortcut_key_right_arrow_or_enter()) self._next.setToolTip(tr.qt_misc_shortcut_key_right_arrow_or_enter())

View file

@ -76,35 +76,48 @@ class SidebarModel(QAbstractItemModel):
return self.createIndex(row, 0, parentItem) return self.createIndex(row, 0, parentItem)
def data(self, index: QModelIndex, role: int = Qt.DisplayRole) -> QVariant: def data(
self, index: QModelIndex, role: int = Qt.ItemDataRole.DisplayRole
) -> QVariant:
if not index.isValid(): if not index.isValid():
return QVariant() return QVariant()
if role not in (Qt.DisplayRole, Qt.DecorationRole, Qt.ToolTipRole, Qt.EditRole): if role not in (
Qt.ItemDataRole.DisplayRole,
Qt.ItemDataRole.DecorationRole,
Qt.ItemDataRole.ToolTipRole,
Qt.ItemDataRole.EditRole,
):
return QVariant() return QVariant()
item: SidebarItem = index.internalPointer() item: SidebarItem = index.internalPointer()
if role in (Qt.DisplayRole, Qt.EditRole): if role in (Qt.ItemDataRole.DisplayRole, Qt.ItemDataRole.EditRole):
return QVariant(item.name) return QVariant(item.name)
if role == Qt.ToolTipRole: if role == Qt.ItemDataRole.ToolTipRole:
return QVariant(item.tooltip) return QVariant(item.tooltip)
return QVariant(theme_manager.icon_from_resources(item.icon)) return QVariant(theme_manager.icon_from_resources(item.icon))
def setData(self, index: QModelIndex, text: str, _role: int = Qt.EditRole) -> bool: def setData(
self, index: QModelIndex, text: str, _role: int = Qt.ItemDataRole.EditRole
) -> bool:
return self.sidebar._on_rename(index.internalPointer(), text) return self.sidebar._on_rename(index.internalPointer(), text)
def supportedDropActions(self) -> Qt.DropActions: def supportedDropActions(self) -> Qt.DropAction:
return cast(Qt.DropActions, Qt.MoveAction) return cast(Qt.DropAction, Qt.DropAction.MoveAction)
def flags(self, index: QModelIndex) -> Qt.ItemFlags: def flags(self, index: QModelIndex) -> Qt.ItemFlag:
if not index.isValid(): if not index.isValid():
return cast(Qt.ItemFlags, Qt.ItemIsEnabled) return cast(Qt.ItemFlag, Qt.ItemFlag.ItemIsEnabled)
flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled flags = (
Qt.ItemFlag.ItemIsEnabled
| Qt.ItemFlag.ItemIsSelectable
| Qt.ItemFlag.ItemIsDragEnabled
)
item: SidebarItem = index.internalPointer() item: SidebarItem = index.internalPointer()
if item.item_type in self.sidebar.valid_drop_types: if item.item_type in self.sidebar.valid_drop_types:
flags |= Qt.ItemIsDropEnabled flags |= Qt.ItemFlag.ItemIsDropEnabled
if item.item_type.is_editable(): if item.item_type.is_editable():
flags |= Qt.ItemIsEditable flags |= Qt.ItemFlag.ItemIsEditable
return cast(Qt.ItemFlags, flags) return flags

View file

@ -43,9 +43,9 @@ class SidebarSearchBar(QLineEdit):
self.sidebar.search_for(self.text()) self.sidebar.search_for(self.text())
def keyPressEvent(self, evt: QKeyEvent) -> None: def keyPressEvent(self, evt: QKeyEvent) -> None:
if evt.key() in (Qt.Key_Up, Qt.Key_Down): if evt.key() in (Qt.Key.Key_Up, Qt.Key.Key_Down):
self.sidebar.setFocus() self.sidebar.setFocus()
elif evt.key() in (Qt.Key_Enter, Qt.Key_Return): elif evt.key() in (Qt.Key.Key_Enter, Qt.Key.Key_Return):
self.onSearch() self.onSearch()
else: else:
QLineEdit.keyPressEvent(self, evt) QLineEdit.keyPressEvent(self, evt)

View file

@ -29,7 +29,7 @@ class SidebarToolbar(QToolBar):
qconnect(self._action_group.triggered, self._on_action_group_triggered) qconnect(self._action_group.triggered, self._on_action_group_triggered)
self._setup_tools() self._setup_tools()
self.setIconSize(QSize(16, 16)) self.setIconSize(QSize(16, 16))
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
self.setStyle(QStyleFactory.create("fusion")) self.setStyle(QStyleFactory.create("fusion"))
def _setup_tools(self) -> None: def _setup_tools(self) -> None:

View file

@ -79,14 +79,14 @@ class SidebarTreeView(QTreeView):
self.valid_drop_types: tuple[SidebarItemType, ...] = () self.valid_drop_types: tuple[SidebarItemType, ...] = ()
self._refresh_needed = False self._refresh_needed = False
self.setContextMenuPolicy(Qt.CustomContextMenu) self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
self.customContextMenuRequested.connect(self.onContextMenu) # type: ignore self.customContextMenuRequested.connect(self.onContextMenu) # type: ignore
self.setUniformRowHeights(True) self.setUniformRowHeights(True)
self.setHeaderHidden(True) self.setHeaderHidden(True)
self.setIndentation(15) self.setIndentation(15)
self.setAutoExpandDelay(600) self.setAutoExpandDelay(600)
self.setDragDropOverwriteMode(False) self.setDragDropOverwriteMode(False)
self.setEditTriggers(QAbstractItemView.EditKeyPressed) self.setEditTriggers(QAbstractItemView.EditTrigger.EditKeyPressed)
qconnect(self.expanded, self._on_expansion) qconnect(self.expanded, self._on_expansion)
qconnect(self.collapsed, self._on_collapse) qconnect(self.collapsed, self._on_collapse)
@ -122,12 +122,12 @@ class SidebarTreeView(QTreeView):
def tool(self, tool: SidebarTool) -> None: def tool(self, tool: SidebarTool) -> None:
self._tool = tool self._tool = tool
if tool == SidebarTool.SEARCH: if tool == SidebarTool.SEARCH:
selection_mode = QAbstractItemView.SingleSelection selection_mode = QAbstractItemView.SelectionMode.SingleSelection
drag_drop_mode = QAbstractItemView.NoDragDrop drag_drop_mode = QAbstractItemView.DragDropMode.NoDragDrop
double_click_expands = False double_click_expands = False
else: else:
selection_mode = QAbstractItemView.ExtendedSelection selection_mode = QAbstractItemView.SelectionMode.ExtendedSelection
drag_drop_mode = QAbstractItemView.InternalMove drag_drop_mode = QAbstractItemView.DragDropMode.InternalMove
double_click_expands = True double_click_expands = True
self.setSelectionMode(selection_mode) self.setSelectionMode(selection_mode)
self.setDragDropMode(drag_drop_mode) self.setDragDropMode(drag_drop_mode)
@ -191,9 +191,9 @@ class SidebarTreeView(QTreeView):
if current := self.find_item(current.has_same_id): if current := self.find_item(current.has_same_id):
index = self.model().index_for_item(current) index = self.model().index_for_item(current)
self.selectionModel().setCurrentIndex( self.selectionModel().setCurrentIndex(
index, QItemSelectionModel.SelectCurrent index, QItemSelectionModel.SelectionFlag.SelectCurrent
) )
self.scrollTo(index, QAbstractItemView.PositionAtCenter) self.scrollTo(index, QAbstractItemView.ScrollHint.PositionAtCenter)
def find_item( def find_item(
self, self,
@ -247,9 +247,12 @@ class SidebarTreeView(QTreeView):
self.setExpanded(idx, True) self.setExpanded(idx, True)
if item.is_highlighted() and scroll_to_first_match: if item.is_highlighted() and scroll_to_first_match:
self.selectionModel().setCurrentIndex( self.selectionModel().setCurrentIndex(
idx, QItemSelectionModel.SelectCurrent idx,
QItemSelectionModel.SelectionFlag.SelectCurrent,
)
self.scrollTo(
idx, QAbstractItemView.ScrollHint.PositionAtCenter
) )
self.scrollTo(idx, QAbstractItemView.PositionAtCenter)
scroll_to_first_match = False scroll_to_first_match = False
expand_node(parent or QModelIndex()) expand_node(parent or QModelIndex())
@ -301,22 +304,29 @@ class SidebarTreeView(QTreeView):
def dropEvent(self, event: QDropEvent) -> None: def dropEvent(self, event: QDropEvent) -> None:
model = self.model() model = self.model()
target_item = model.item_for_index(self.indexAt(event.pos())) if qtmajor == 5:
pos = event.pos() # type: ignore
else:
pos = event.position().toPoint()
target_item = model.item_for_index(self.indexAt(pos))
if self.handle_drag_drop(self._selected_items(), target_item): if self.handle_drag_drop(self._selected_items(), target_item):
event.acceptProposedAction() event.acceptProposedAction()
def mouseReleaseEvent(self, event: QMouseEvent) -> None: def mouseReleaseEvent(self, event: QMouseEvent) -> None:
super().mouseReleaseEvent(event) super().mouseReleaseEvent(event)
if self.tool == SidebarTool.SEARCH and event.button() == Qt.LeftButton: if (
self.tool == SidebarTool.SEARCH
and event.button() == Qt.MouseButton.LeftButton
):
if (index := self.currentIndex()) == self.indexAt(event.pos()): if (index := self.currentIndex()) == self.indexAt(event.pos()):
self._on_search(index) self._on_search(index)
def keyPressEvent(self, event: QKeyEvent) -> None: def keyPressEvent(self, event: QKeyEvent) -> None:
index = self.currentIndex() index = self.currentIndex()
if event.key() in (Qt.Key_Return, Qt.Key_Enter): if event.key() in (Qt.Key.Key_Return, Qt.Key.Key_Enter):
if not self.isPersistentEditorOpen(index): if not self.isPersistentEditorOpen(index):
self._on_search(index) self._on_search(index)
elif event.key() == Qt.Key_Delete: elif event.key() == Qt.Key.Key_Delete:
self._on_delete_key(index) self._on_delete_key(index)
else: else:
super().keyPressEvent(event) super().keyPressEvent(event)

View file

@ -3,7 +3,7 @@
from __future__ import annotations from __future__ import annotations
import time import time
from typing import Any, Callable, Sequence, cast from typing import Any, Callable, Sequence
import aqt import aqt
from anki.cards import Card, CardId from anki.cards import Card, CardId
@ -307,7 +307,7 @@ class DataModel(QAbstractTableModel):
def data(self, index: QModelIndex = QModelIndex(), role: int = 0) -> Any: def data(self, index: QModelIndex = QModelIndex(), role: int = 0) -> Any:
if not index.isValid(): if not index.isValid():
return QVariant() return QVariant()
if role == Qt.FontRole: if role == Qt.ItemDataRole.FontRole:
if not self.column_at(index).uses_cell_font: if not self.column_at(index).uses_cell_font:
return QVariant() return QVariant()
qfont = QFont() qfont = QFont()
@ -315,30 +315,33 @@ class DataModel(QAbstractTableModel):
qfont.setFamily(row.font_name) qfont.setFamily(row.font_name)
qfont.setPixelSize(row.font_size) qfont.setPixelSize(row.font_size)
return qfont return qfont
elif role == Qt.TextAlignmentRole: elif role == Qt.ItemDataRole.TextAlignmentRole:
align: Qt.AlignmentFlag | int = Qt.AlignVCenter align: Qt.AlignmentFlag | int = Qt.AlignmentFlag.AlignVCenter
if self.column_at(index).alignment == Columns.ALIGNMENT_CENTER: if self.column_at(index).alignment == Columns.ALIGNMENT_CENTER:
align |= Qt.AlignHCenter align |= Qt.AlignmentFlag.AlignHCenter
return align return align
elif role == Qt.DisplayRole: elif role == Qt.ItemDataRole.DisplayRole:
return self.get_cell(index).text return self.get_cell(index).text
elif role == Qt.ToolTipRole and self._want_tooltips: elif role == Qt.ItemDataRole.ToolTipRole and self._want_tooltips:
return self.get_cell(index).text return self.get_cell(index).text
return QVariant() return QVariant()
def headerData( def headerData(
self, section: int, orientation: Qt.Orientation, role: int = 0 self, section: int, orientation: Qt.Orientation, role: int = 0
) -> str | None: ) -> str | None:
if orientation == Qt.Horizontal and role == Qt.DisplayRole: if (
orientation == Qt.Orientation.Horizontal
and role == Qt.ItemDataRole.DisplayRole
):
return self._state.column_label(self.column_at_section(section)) return self._state.column_label(self.column_at_section(section))
return None return None
def flags(self, index: QModelIndex) -> Qt.ItemFlags: def flags(self, index: QModelIndex) -> Qt.ItemFlag:
# shortcut for large selections (Ctrl+A) to avoid fetching large numbers of rows at once # shortcut for large selections (Ctrl+A) to avoid fetching large numbers of rows at once
if row := self.get_cached_row(index): if row := self.get_cached_row(index):
if row.is_deleted: if row.is_deleted:
return Qt.ItemFlags(Qt.NoItemFlags) return Qt.ItemFlag(Qt.ItemFlag.NoItemFlags)
return cast(Qt.ItemFlags, Qt.ItemIsEnabled | Qt.ItemIsSelectable) return Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable
def addon_column_fillin(key: str) -> Column: def addon_column_fillin(key: str) -> Column:

View file

@ -2,7 +2,7 @@
# 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 __future__ import annotations from __future__ import annotations
from typing import Any, Callable, Sequence, cast from typing import Any, Callable, Sequence
import aqt import aqt
import aqt.forms import aqt.forms
@ -127,10 +127,8 @@ class Table:
self.select_all() self.select_all()
self._view.selectionModel().select( self._view.selectionModel().select(
selection, selection,
cast( QItemSelectionModel.SelectionFlag.Deselect
QItemSelectionModel.SelectionFlags, | QItemSelectionModel.SelectionFlag.Rows,
QItemSelectionModel.Deselect | QItemSelectionModel.Rows,
),
) )
def select_single_card(self, card_id: CardId) -> None: def select_single_card(self, card_id: CardId) -> None:
@ -202,10 +200,10 @@ class Table:
# Move cursor # Move cursor
def to_previous_row(self) -> None: def to_previous_row(self) -> None:
self._move_current(QAbstractItemView.MoveUp) self._move_current(QAbstractItemView.CursorAction.MoveUp)
def to_next_row(self) -> None: def to_next_row(self) -> None:
self._move_current(QAbstractItemView.MoveDown) self._move_current(QAbstractItemView.CursorAction.MoveDown)
def to_first_row(self) -> None: def to_first_row(self) -> None:
self._move_current_to_row(0) self._move_current_to_row(0)
@ -248,7 +246,8 @@ class Table:
def clear_current(self) -> None: def clear_current(self) -> None:
self._view.selectionModel().setCurrentIndex( self._view.selectionModel().setCurrentIndex(
QModelIndex(), QItemSelectionModel.NoUpdate QModelIndex(),
QItemSelectionModel.SelectionFlag.NoUpdate,
) )
# Private methods # Private methods
@ -268,7 +267,10 @@ class Table:
index = self._model.index( index = self._model.index(
row, self._view.horizontalHeader().logicalIndex(column) row, self._view.horizontalHeader().logicalIndex(column)
) )
self._view.selectionModel().setCurrentIndex(index, QItemSelectionModel.NoUpdate) self._view.selectionModel().setCurrentIndex(
index,
QItemSelectionModel.SelectionFlag.NoUpdate,
)
def _reset_selection(self) -> None: def _reset_selection(self) -> None:
"""Remove selection and focus without emitting signals. """Remove selection and focus without emitting signals.
@ -286,7 +288,9 @@ class Table:
self._model.index(row, 0), self._model.index(row, 0),
self._model.index(row, self._model.len_columns() - 1), self._model.index(row, self._model.len_columns() - 1),
) )
self._view.selectionModel().select(selection, QItemSelectionModel.SelectCurrent) self._view.selectionModel().select(
selection, QItemSelectionModel.SelectionFlag.SelectCurrent
)
def _set_sort_indicator(self) -> None: def _set_sort_indicator(self) -> None:
hh = self._view.horizontalHeader() hh = self._view.horizontalHeader()
@ -295,9 +299,9 @@ class Table:
hh.setSortIndicatorShown(False) hh.setSortIndicatorShown(False)
return return
if self._state.sort_backwards: if self._state.sort_backwards:
order = Qt.DescendingOrder order = Qt.SortOrder.DescendingOrder
else: else:
order = Qt.AscendingOrder order = Qt.SortOrder.AscendingOrder
hh.blockSignals(True) hh.blockSignals(True)
hh.setSortIndicator(index, order) hh.setSortIndicator(index, order)
hh.blockSignals(False) hh.blockSignals(False)
@ -305,9 +309,10 @@ class Table:
def _set_column_sizes(self) -> None: def _set_column_sizes(self) -> None:
hh = self._view.horizontalHeader() hh = self._view.horizontalHeader()
hh.setSectionResizeMode(QHeaderView.Interactive) hh.setSectionResizeMode(QHeaderView.ResizeMode.Interactive)
hh.setSectionResizeMode( hh.setSectionResizeMode(
hh.logicalIndex(self._model.len_columns() - 1), QHeaderView.Stretch hh.logicalIndex(self._model.len_columns() - 1),
QHeaderView.ResizeMode.Stretch,
) )
# this must be set post-resize or it doesn't work # this must be set post-resize or it doesn't work
hh.setCascadingSectionResizes(False) hh.setCascadingSectionResizes(False)
@ -334,7 +339,7 @@ class Table:
) )
qconnect(self._view.selectionModel().currentChanged, self._on_current_changed) qconnect(self._view.selectionModel().currentChanged, self._on_current_changed)
self._view.setWordWrap(False) self._view.setWordWrap(False)
self._view.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel) self._view.setHorizontalScrollMode(QAbstractItemView.ScrollMode.ScrollPerPixel)
self._view.horizontalScrollBar().setSingleStep(10) self._view.horizontalScrollBar().setSingleStep(10)
self._update_font() self._update_font()
if not theme_manager.night_mode: if not theme_manager.night_mode:
@ -346,7 +351,7 @@ class Table:
self._view.setStyleSheet( self._view.setStyleSheet(
f"QTableView {{ gridline-color: {colors.FRAME_BG} }}" f"QTableView {{ gridline-color: {colors.FRAME_BG} }}"
) )
self._view.setContextMenuPolicy(Qt.CustomContextMenu) self._view.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
qconnect(self._view.customContextMenuRequested, self._on_context_menu) qconnect(self._view.customContextMenuRequested, self._on_context_menu)
def _update_font(self) -> None: def _update_font(self) -> None:
@ -369,7 +374,7 @@ class Table:
hh.setHighlightSections(False) hh.setHighlightSections(False)
hh.setMinimumSectionSize(50) hh.setMinimumSectionSize(50)
hh.setSectionsMovable(True) hh.setSectionsMovable(True)
hh.setContextMenuPolicy(Qt.CustomContextMenu) hh.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
self._restore_header() self._restore_header()
qconnect(hh.customContextMenuRequested, self._on_header_context) qconnect(hh.customContextMenuRequested, self._on_header_context)
qconnect(hh.sortIndicatorChanged, self._on_sort_column_changed) qconnect(hh.sortIndicatorChanged, self._on_sort_column_changed)
@ -573,7 +578,9 @@ class Table:
visible = top_border >= 0 and bottom_border < self._view.viewport().height() visible = top_border >= 0 and bottom_border < self._view.viewport().height()
if not visible or scroll_even_if_visible: if not visible or scroll_even_if_visible:
horizontal = self._view.horizontalScrollBar().value() horizontal = self._view.horizontalScrollBar().value()
self._view.scrollTo(self._model.index(row, 0), self._view.PositionAtTop) self._view.scrollTo(
self._model.index(row, 0), QAbstractItemView.ScrollHint.PositionAtTop
)
self._view.horizontalScrollBar().setValue(horizontal) self._view.horizontalScrollBar().setValue(horizontal)
def _scroll_to_column(self, column: int) -> None: def _scroll_to_column(self, column: int) -> None:
@ -583,26 +590,26 @@ class Table:
if not visible: if not visible:
vertical = self._view.verticalScrollBar().value() vertical = self._view.verticalScrollBar().value()
self._view.scrollTo( self._view.scrollTo(
self._model.index(0, column), self._view.PositionAtCenter self._model.index(0, column),
QAbstractItemView.ScrollHint.PositionAtCenter,
) )
self._view.verticalScrollBar().setValue(vertical) self._view.verticalScrollBar().setValue(vertical)
def _move_current(self, direction: int, index: QModelIndex = None) -> None: def _move_current(
self, direction: QAbstractItemView.CursorAction, index: QModelIndex = None
) -> None:
if not self.has_current(): if not self.has_current():
return return
if index is None: if index is None:
index = self._view.moveCursor( index = self._view.moveCursor(
cast(QAbstractItemView.CursorAction, direction), direction,
self.browser.mw.app.keyboardModifiers(), self.browser.mw.app.keyboardModifiers(),
) )
self._view.selectionModel().setCurrentIndex( self._view.selectionModel().setCurrentIndex(
index, index,
cast( QItemSelectionModel.SelectionFlag.Clear
QItemSelectionModel.SelectionFlag, | QItemSelectionModel.SelectionFlag.Select
QItemSelectionModel.Clear | QItemSelectionModel.SelectionFlag.Rows,
| QItemSelectionModel.Select
| QItemSelectionModel.Rows,
),
) )
def _move_current_to_row(self, row: int) -> None: def _move_current_to_row(self, row: int) -> None:
@ -614,10 +621,8 @@ class Table:
selection = QItemSelection(new, old) selection = QItemSelection(new, old)
self._view.selectionModel().select( self._view.selectionModel().select(
selection, selection,
cast( QItemSelectionModel.SelectionFlag.SelectCurrent
QItemSelectionModel.SelectionFlag, | QItemSelectionModel.SelectionFlag.Rows,
QItemSelectionModel.SelectCurrent | QItemSelectionModel.Rows,
),
) )
@ -630,7 +635,7 @@ class StatusDelegate(QItemDelegate):
self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex
) -> None: ) -> None:
if self._model.get_cell(index).is_rtl: if self._model.get_cell(index).is_rtl:
option.direction = Qt.RightToLeft option.direction = Qt.LayoutDirection.RightToLeft
if row_color := self._model.get_row(index).color: if row_color := self._model.get_row(index).color:
brush = QBrush(theme_manager.qcolor(row_color)) brush = QBrush(theme_manager.qcolor(row_color))
painter.save() painter.save()

View file

@ -43,7 +43,7 @@ class ChangeNotetypeDialog(QDialog):
self.show() self.show()
def _setup_ui(self, notetype_id: NotetypeId) -> None: def _setup_ui(self, notetype_id: NotetypeId) -> None:
self.setWindowModality(Qt.ApplicationModal) self.setWindowModality(Qt.WindowModality.ApplicationModal)
self.mw.garbage_collect_on_dialog_finish(self) self.mw.garbage_collect_on_dialog_finish(self)
self.setMinimumWidth(400) self.setMinimumWidth(400)
disable_help_button(self) disable_help_button(self)

View file

@ -45,7 +45,7 @@ class CardLayout(QDialog):
parent: Optional[QWidget] = None, parent: Optional[QWidget] = None,
fill_empty: bool = False, fill_empty: bool = False,
) -> None: ) -> None:
QDialog.__init__(self, parent or mw, Qt.Window) QDialog.__init__(self, parent or mw, Qt.WindowType.Window)
mw.garbage_collect_on_dialog_finish(self) mw.garbage_collect_on_dialog_finish(self)
self.mw = aqt.mw self.mw = aqt.mw
self.note = note self.note = note
@ -80,7 +80,7 @@ class CardLayout(QDialog):
self.redraw_everything() self.redraw_everything()
restoreGeom(self, "CardLayout") restoreGeom(self, "CardLayout")
restoreSplitter(self.mainArea, "CardLayoutMainArea") restoreSplitter(self.mainArea, "CardLayoutMainArea")
self.setWindowModality(Qt.ApplicationModal) self.setWindowModality(Qt.WindowModality.ApplicationModal)
self.show() self.show()
# take the focus away from the first input area when starting up, # take the focus away from the first input area when starting up,
# as users tend to accidentally type into the template # as users tend to accidentally type into the template
@ -108,7 +108,9 @@ class CardLayout(QDialog):
def setupTopArea(self) -> None: def setupTopArea(self) -> None:
self.topArea = QWidget() self.topArea = QWidget()
self.topArea.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum) self.topArea.setSizePolicy(
QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum
)
self.topAreaForm = aqt.forms.clayout_top.Ui_Form() self.topAreaForm = aqt.forms.clayout_top.Ui_Form()
self.topAreaForm.setupUi(self.topArea) self.topAreaForm.setupUi(self.topArea)
self.topAreaForm.templateOptions.setText( self.topAreaForm.templateOptions.setText(
@ -215,8 +217,8 @@ class CardLayout(QDialog):
def setupMainArea(self) -> None: def setupMainArea(self) -> None:
split = self.mainArea = QSplitter() split = self.mainArea = QSplitter()
split.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) split.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
split.setOrientation(Qt.Horizontal) split.setOrientation(Qt.Orientation.Horizontal)
left = QWidget() left = QWidget()
tform = self.tform = aqt.forms.template.Ui_Form() tform = self.tform = aqt.forms.template.Ui_Form()
tform.setupUi(left) tform.setupUi(left)
@ -305,7 +307,7 @@ class CardLayout(QDialog):
if not editor.find(text): if not editor.find(text):
# try again from top # try again from top
cursor = editor.textCursor() cursor = editor.textCursor()
cursor.movePosition(QTextCursor.Start) cursor.movePosition(QTextCursor.MoveOperation.Start)
editor.setTextCursor(cursor) editor.setTextCursor(cursor)
if not editor.find(text): if not editor.find(text):
tooltip("No matches found.") tooltip("No matches found.")
@ -752,7 +754,7 @@ class CardLayout(QDialog):
if t["did"]: if t["did"]:
te.setText(self.col.decks.get(t["did"])["name"]) te.setText(self.col.decks.get(t["did"])["name"])
te.selectAll() te.selectAll()
bb = QDialogButtonBox(QDialogButtonBox.Close) bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Close)
qconnect(bb.rejected, d.close) qconnect(bb.rejected, d.close)
l.addWidget(bb) l.addWidget(bb)
d.setLayout(l) d.setLayout(l)

View file

@ -30,7 +30,7 @@ class CustomStudy(QDialog):
self.created_custom_study = False self.created_custom_study = False
f.setupUi(self) f.setupUi(self)
disable_help_button(self) disable_help_button(self)
self.setWindowModality(Qt.WindowModal) self.setWindowModality(Qt.WindowModality.WindowModal)
self.setupSignals() self.setupSignals()
f.radioNew.click() f.radioNew.click()
self.exec() self.exec()
@ -116,7 +116,7 @@ class CustomStudy(QDialog):
f.spin.setValue(sval) f.spin.setValue(sval)
f.preSpin.setText(pre) f.preSpin.setText(pre)
f.postSpin.setText(post) f.postSpin.setText(post)
f.buttonBox.button(QDialogButtonBox.Ok).setText(ok) f.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setText(ok)
self.radioIdx = idx self.radioIdx = idx
def accept(self) -> None: def accept(self) -> None:

View file

@ -40,13 +40,15 @@ class DeckConf(QDialog):
self.mw.checkpoint(tr.actions_options()) self.mw.checkpoint(tr.actions_options())
self.setupCombos() self.setupCombos()
self.setupConfs() self.setupConfs()
self.setWindowModality(Qt.WindowModal) self.setWindowModality(Qt.WindowModality.WindowModal)
qconnect( qconnect(
self.form.buttonBox.helpRequested, lambda: openHelp(HelpPage.DECK_OPTIONS) self.form.buttonBox.helpRequested, lambda: openHelp(HelpPage.DECK_OPTIONS)
) )
qconnect(self.form.confOpts.clicked, self.confOpts) qconnect(self.form.confOpts.clicked, self.confOpts)
qconnect( qconnect(
self.form.buttonBox.button(QDialogButtonBox.RestoreDefaults).clicked, self.form.buttonBox.button(
QDialogButtonBox.StandardButton.RestoreDefaults
).clicked,
self.onRestore, self.onRestore,
) )
self.setWindowTitle( self.setWindowTitle(

View file

@ -17,7 +17,7 @@ class DeckDescriptionDialog(QDialog):
silentlyClose = True silentlyClose = True
def __init__(self, mw: aqt.main.AnkiQt) -> None: def __init__(self, mw: aqt.main.AnkiQt) -> None:
QDialog.__init__(self, mw, Qt.Window) QDialog.__init__(self, mw, Qt.WindowType.Window)
self.mw = mw self.mw = mw
# set on success # set on success
@ -39,7 +39,7 @@ class DeckDescriptionDialog(QDialog):
def _setup_ui(self) -> None: def _setup_ui(self) -> None:
self.setWindowTitle(tr.scheduling_description()) self.setWindowTitle(tr.scheduling_description())
self.setWindowModality(Qt.ApplicationModal) self.setWindowModality(Qt.WindowModality.ApplicationModal)
self.mw.garbage_collect_on_dialog_finish(self) self.mw.garbage_collect_on_dialog_finish(self)
self.setMinimumWidth(400) self.setMinimumWidth(400)
disable_help_button(self) disable_help_button(self)
@ -58,7 +58,7 @@ class DeckDescriptionDialog(QDialog):
box.addWidget(self.description) box.addWidget(self.description)
button_box = QDialogButtonBox() button_box = QDialogButtonBox()
ok = button_box.addButton(QDialogButtonBox.Ok) ok = button_box.addButton(QDialogButtonBox.StandardButton.Ok)
qconnect(ok.clicked, self.save_and_accept) qconnect(ok.clicked, self.save_and_accept)
box.addWidget(button_box) box.addWidget(button_box)

View file

@ -28,14 +28,14 @@ class DeckOptionsDialog(QDialog):
silentlyClose = True silentlyClose = True
def __init__(self, mw: aqt.main.AnkiQt, deck: DeckDict) -> None: def __init__(self, mw: aqt.main.AnkiQt, deck: DeckDict) -> None:
QDialog.__init__(self, mw, Qt.Window) QDialog.__init__(self, mw, Qt.WindowType.Window)
self.mw = mw self.mw = mw
self._deck = deck self._deck = deck
self._setup_ui() self._setup_ui()
self.show() self.show()
def _setup_ui(self) -> None: def _setup_ui(self) -> None:
self.setWindowModality(Qt.ApplicationModal) self.setWindowModality(Qt.WindowModality.ApplicationModal)
self.mw.garbage_collect_on_dialog_finish(self) self.mw.garbage_collect_on_dialog_finish(self)
self.setMinimumWidth(400) self.setMinimumWidth(400)
disable_help_button(self) disable_help_button(self)

View file

@ -12,7 +12,7 @@ from aqt.utils import disable_help_button, restoreGeom, saveGeom, tr
class EditCurrent(QDialog): class EditCurrent(QDialog):
def __init__(self, mw: aqt.AnkiQt) -> None: def __init__(self, mw: aqt.AnkiQt) -> None:
QDialog.__init__(self, None, Qt.Window) QDialog.__init__(self, None, Qt.WindowType.Window)
mw.garbage_collect_on_dialog_finish(self) mw.garbage_collect_on_dialog_finish(self)
self.mw = mw self.mw = mw
self.form = aqt.forms.editcurrent.Ui_Dialog() self.form = aqt.forms.editcurrent.Ui_Dialog()
@ -21,7 +21,7 @@ class EditCurrent(QDialog):
disable_help_button(self) disable_help_button(self)
self.setMinimumHeight(400) self.setMinimumHeight(400)
self.setMinimumWidth(250) self.setMinimumWidth(250)
self.form.buttonBox.button(QDialogButtonBox.Close).setShortcut( self.form.buttonBox.button(QDialogButtonBox.StandardButton.Close).setShortcut(
QKeySequence("Ctrl+Return") QKeySequence("Ctrl+Return")
) )
self.editor = aqt.editor.Editor(self.mw, self.form.fieldsArea, self) self.editor = aqt.editor.Editor(self.mw, self.form.fieldsArea, self)

View file

@ -902,7 +902,7 @@ $editorToolbar.then(({{ toolbar }}) => toolbar.appendGroup({{
@deprecated(info=_js_legacy) @deprecated(info=_js_legacy)
def _onHtmlEdit(self, field: int) -> None: def _onHtmlEdit(self, field: int) -> None:
d = QDialog(self.widget, Qt.Window) d = QDialog(self.widget, Qt.WindowType.Window)
form = aqt.forms.edithtml.Ui_Dialog() form = aqt.forms.edithtml.Ui_Dialog()
form.setupUi(d) form.setupUi(d)
restoreGeom(d, "htmlEditor") restoreGeom(d, "htmlEditor")
@ -911,11 +911,11 @@ $editorToolbar.then(({{ toolbar }}) => toolbar.appendGroup({{
form.buttonBox.helpRequested, lambda: openHelp(HelpPage.EDITING_FEATURES) form.buttonBox.helpRequested, lambda: openHelp(HelpPage.EDITING_FEATURES)
) )
font = QFont("Courier") font = QFont("Courier")
font.setStyleHint(QFont.TypeWriter) font.setStyleHint(QFont.StyleHint.TypeWriter)
form.textEdit.setFont(font) form.textEdit.setFont(font)
form.textEdit.setPlainText(self.note.fields[field]) form.textEdit.setPlainText(self.note.fields[field])
d.show() d.show()
form.textEdit.moveCursor(QTextCursor.End) form.textEdit.moveCursor(QTextCursor.MoveOperation.End)
d.exec() d.exec()
html = form.textEdit.toPlainText() html = form.textEdit.toPlainText()
if html.find(">") > -1: if html.find(">") > -1:
@ -997,7 +997,10 @@ $editorToolbar.then(({{ toolbar }}) => toolbar.appendGroup({{
def onChangeCol(self) -> None: def onChangeCol(self) -> None:
if isLin: if isLin:
new = QColorDialog.getColor( new = QColorDialog.getColor(
QColor(self.fcolour), None, None, QColorDialog.DontUseNativeDialog QColor(self.fcolour),
None,
None,
QColorDialog.ColorDialogOption.DontUseNativeDialog,
) )
else: else:
new = QColorDialog.getColor(QColor(self.fcolour), None) new = QColorDialog.getColor(QColor(self.fcolour), None)
@ -1118,10 +1121,10 @@ class EditorWebView(AnkiWebView):
self._flagAnkiText() self._flagAnkiText()
def onCut(self) -> None: def onCut(self) -> None:
self.triggerPageAction(QWebEnginePage.Cut) self.triggerPageAction(QWebEnginePage.WebAction.Cut)
def onCopy(self) -> None: def onCopy(self) -> None:
self.triggerPageAction(QWebEnginePage.Copy) self.triggerPageAction(QWebEnginePage.WebAction.Copy)
def _wantsExtendedPaste(self) -> bool: def _wantsExtendedPaste(self) -> bool:
strip_html = self.editor.mw.col.get_config_bool( strip_html = self.editor.mw.col.get_config_bool(
@ -1140,10 +1143,10 @@ class EditorWebView(AnkiWebView):
self.editor.doPaste(html, internal, extended) self.editor.doPaste(html, internal, extended)
def onPaste(self) -> None: def onPaste(self) -> None:
self._onPaste(QClipboard.Clipboard) self._onPaste(QClipboard.Mode.Clipboard)
def onMiddleClickPaste(self) -> None: def onMiddleClickPaste(self) -> None:
self._onPaste(QClipboard.Selection) self._onPaste(QClipboard.Mode.Selection)
def dragEnterEvent(self, evt: QDragEnterEvent) -> None: def dragEnterEvent(self, evt: QDragEnterEvent) -> None:
evt.accept() evt.accept()

View file

@ -63,7 +63,7 @@ class EmptyCardsDialog(QDialog):
qconnect(self.finished, on_finished) qconnect(self.finished, on_finished)
self._delete_button = self.form.buttonBox.addButton( self._delete_button = self.form.buttonBox.addButton(
tr.empty_cards_delete_button(), QDialogButtonBox.ActionRole tr.empty_cards_delete_button(), QDialogButtonBox.ButtonRole.ActionRole
) )
self._delete_button.setAutoDefault(False) self._delete_button.setAutoDefault(False)
qconnect(self._delete_button.clicked, self._on_delete) qconnect(self._delete_button.clicked, self._on_delete)

View file

@ -31,7 +31,7 @@ class ExportDialog(QDialog):
did: DeckId | None = None, did: DeckId | None = None,
cids: list[CardId] | None = None, cids: list[CardId] | None = None,
): ):
QDialog.__init__(self, mw, Qt.Window) QDialog.__init__(self, mw, Qt.WindowType.Window)
self.mw = mw self.mw = mw
self.col = mw.col.weakref() self.col = mw.col.weakref()
self.frm = aqt.forms.exporting.Ui_ExportDialog() self.frm = aqt.forms.exporting.Ui_ExportDialog()
@ -64,7 +64,7 @@ class ExportDialog(QDialog):
self.frm.deck.addItems(self.decks) self.frm.deck.addItems(self.decks)
# save button # save button
b = QPushButton(tr.exporting_export()) b = QPushButton(tr.exporting_export())
self.frm.buttonBox.addButton(b, QDialogButtonBox.AcceptRole) self.frm.buttonBox.addButton(b, QDialogButtonBox.ButtonRole.AcceptRole)
# set default option if accessed through deck button # set default option if accessed through deck button
if did: if did:
name = self.mw.col.decks.get(did)["name"] name = self.mw.col.decks.get(did)["name"]

View file

@ -45,13 +45,19 @@ class FieldDialog(QDialog):
without_unicode_isolation(tr.fields_fields_for(val=self.model["name"])) without_unicode_isolation(tr.fields_fields_for(val=self.model["name"]))
) )
disable_help_button(self) disable_help_button(self)
self.form.buttonBox.button(QDialogButtonBox.Help).setAutoDefault(False) self.form.buttonBox.button(QDialogButtonBox.StandardButton.Help).setAutoDefault(
self.form.buttonBox.button(QDialogButtonBox.Cancel).setAutoDefault(False) False
self.form.buttonBox.button(QDialogButtonBox.Save).setAutoDefault(False) )
self.form.buttonBox.button(
QDialogButtonBox.StandardButton.Cancel
).setAutoDefault(False)
self.form.buttonBox.button(QDialogButtonBox.StandardButton.Save).setAutoDefault(
False
)
self.currentIdx: Optional[int] = None self.currentIdx: Optional[int] = None
self.fillFields() self.fillFields()
self.setupSignals() self.setupSignals()
self.form.fieldList.setDragDropMode(QAbstractItemView.InternalMove) self.form.fieldList.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove)
self.form.fieldList.dropEvent = self.onDrop # type: ignore[assignment] self.form.fieldList.dropEvent = self.onDrop # type: ignore[assignment]
self.form.fieldList.setCurrentRow(open_at) self.form.fieldList.setCurrentRow(open_at)
self.exec() self.exec()
@ -77,15 +83,21 @@ class FieldDialog(QDialog):
def onDrop(self, ev: QDropEvent) -> None: def onDrop(self, ev: QDropEvent) -> None:
fieldList = self.form.fieldList fieldList = self.form.fieldList
indicatorPos = fieldList.dropIndicatorPosition() indicatorPos = fieldList.dropIndicatorPosition()
dropPos = fieldList.indexAt(ev.pos()).row() if qtmajor == 5:
pos = ev.pos() # type: ignore
else:
pos = ev.position().toPoint()
dropPos = fieldList.indexAt(pos).row()
idx = self.currentIdx idx = self.currentIdx
if dropPos == idx: if dropPos == idx:
return return
if indicatorPos == QAbstractItemView.OnViewport: # to bottom. if (
indicatorPos == QAbstractItemView.DropIndicatorPosition.OnViewport
): # to bottom.
movePos = fieldList.count() - 1 movePos = fieldList.count() - 1
elif indicatorPos == QAbstractItemView.AboveItem: elif indicatorPos == QAbstractItemView.DropIndicatorPosition.AboveItem:
movePos = dropPos movePos = dropPos
elif indicatorPos == QAbstractItemView.BelowItem: elif indicatorPos == QAbstractItemView.DropIndicatorPosition.BelowItem:
movePos = dropPos + 1 movePos = dropPos + 1
# the item in idx is removed thus subtract 1. # the item in idx is removed thus subtract 1.
if idx < dropPos: if idx < dropPos:

View file

@ -90,7 +90,7 @@ class FilteredDeckConfigDialog(QDialog):
QPushButton[label="hint"] {{ color: {grey} }}""" QPushButton[label="hint"] {{ color: {grey} }}"""
) )
disable_help_button(self) disable_help_button(self)
self.setWindowModality(Qt.WindowModal) self.setWindowModality(Qt.WindowModality.WindowModal)
qconnect( qconnect(
self.form.buttonBox.helpRequested, lambda: openHelp(HelpPage.FILTERED_DECK) self.form.buttonBox.helpRequested, lambda: openHelp(HelpPage.FILTERED_DECK)
) )
@ -117,7 +117,9 @@ class FilteredDeckConfigDialog(QDialog):
build_label = tr.actions_rebuild() build_label = tr.actions_rebuild()
else: else:
build_label = tr.decks_build() build_label = tr.decks_build()
self.form.buttonBox.button(QDialogButtonBox.Ok).setText(build_label) self.form.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setText(
build_label
)
form.resched.setChecked(config.reschedule) form.resched.setChecked(config.reschedule)
self._onReschedToggled(0) self._onReschedToggled(0)

View file

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>377</width> <width>479</width>
<height>224</height> <height>247</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -31,7 +31,7 @@
<enum>QComboBox::NoInsert</enum> <enum>QComboBox::NoInsert</enum>
</property> </property>
<property name="sizeAdjustPolicy"> <property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLength</enum> <enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
</property> </property>
</widget> </widget>
</item> </item>
@ -59,7 +59,7 @@
<item row="2" column="1"> <item row="2" column="1">
<widget class="QComboBox" name="field"> <widget class="QComboBox" name="field">
<property name="sizeAdjustPolicy"> <property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLength</enum> <enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
</property> </property>
</widget> </widget>
</item> </item>
@ -95,7 +95,7 @@
<enum>QComboBox::NoInsert</enum> <enum>QComboBox::NoInsert</enum>
</property> </property>
<property name="sizeAdjustPolicy"> <property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLength</enum> <enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
</property> </property>
</widget> </widget>
</item> </item>

View file

@ -35,7 +35,7 @@ from aqt.utils import (
class ChangeMap(QDialog): class ChangeMap(QDialog):
def __init__(self, mw: AnkiQt, model: dict, current: str) -> None: def __init__(self, mw: AnkiQt, model: dict, current: str) -> None:
QDialog.__init__(self, mw, Qt.Window) QDialog.__init__(self, mw, Qt.WindowType.Window)
self.mw = mw self.mw = mw
self.model = model self.model = model
self.frm = aqt.forms.changemap.Ui_ChangeMap() self.frm = aqt.forms.changemap.Ui_ChangeMap()
@ -85,13 +85,14 @@ class ImportDialog(QDialog):
_DEFAULT_FILE_DELIMITER = "\t" _DEFAULT_FILE_DELIMITER = "\t"
def __init__(self, mw: AnkiQt, importer: Any) -> None: def __init__(self, mw: AnkiQt, importer: Any) -> None:
QDialog.__init__(self, mw, Qt.Window) QDialog.__init__(self, mw, Qt.WindowType.Window)
self.mw = mw self.mw = mw
self.importer = importer self.importer = importer
self.frm = aqt.forms.importing.Ui_ImportDialog() self.frm = aqt.forms.importing.Ui_ImportDialog()
self.frm.setupUi(self) self.frm.setupUi(self)
qconnect( qconnect(
self.frm.buttonBox.button(QDialogButtonBox.Help).clicked, self.helpRequested self.frm.buttonBox.button(QDialogButtonBox.StandardButton.Help).clicked,
self.helpRequested,
) )
disable_help_button(self) disable_help_button(self)
self.setupMappingFrame() self.setupMappingFrame()
@ -108,7 +109,7 @@ class ImportDialog(QDialog):
self.frm.tagModified.setCol(self.mw.col) self.frm.tagModified.setCol(self.mw.col)
# import button # import button
b = QPushButton(tr.actions_import()) b = QPushButton(tr.actions_import())
self.frm.buttonBox.addButton(b, QDialogButtonBox.AcceptRole) self.frm.buttonBox.addButton(b, QDialogButtonBox.ButtonRole.AcceptRole)
self.exec() self.exec()
def setupOptions(self) -> None: def setupOptions(self) -> None:

View file

@ -107,10 +107,7 @@ class AnkiQt(QMainWindow):
self.pm = profileManager self.pm = profileManager
# init rest of app # init rest of app
self.safeMode = ( self.safeMode = (
bool( bool(self.app.queryKeyboardModifiers() & Qt.KeyboardModifier.ShiftModifier)
cast(Qt.KeyboardModifier, self.app.queryKeyboardModifiers())
& Qt.ShiftModifier
)
or self.opts.safemode or self.opts.safemode
) )
try: try:
@ -817,15 +814,15 @@ title="{}" {}>{}</button>""".format(
self.form.setupUi(self) self.form.setupUi(self)
# toolbar # toolbar
tweb = self.toolbarWeb = aqt.webview.AnkiWebView(title="top toolbar") tweb = self.toolbarWeb = aqt.webview.AnkiWebView(title="top toolbar")
tweb.setFocusPolicy(Qt.WheelFocus) tweb.setFocusPolicy(Qt.FocusPolicy.WheelFocus)
self.toolbar = aqt.toolbar.Toolbar(self, tweb) self.toolbar = aqt.toolbar.Toolbar(self, tweb)
# main area # main area
self.web = aqt.webview.AnkiWebView(title="main webview") self.web = aqt.webview.AnkiWebView(title="main webview")
self.web.setFocusPolicy(Qt.WheelFocus) self.web.setFocusPolicy(Qt.FocusPolicy.WheelFocus)
self.web.setMinimumWidth(400) self.web.setMinimumWidth(400)
# bottom area # bottom area
sweb = self.bottomWeb = aqt.webview.AnkiWebView(title="bottom toolbar") sweb = self.bottomWeb = aqt.webview.AnkiWebView(title="bottom toolbar")
sweb.setFocusPolicy(Qt.WheelFocus) sweb.setFocusPolicy(Qt.FocusPolicy.WheelFocus)
# add in a layout # add in a layout
self.mainLayout = QVBoxLayout() self.mainLayout = QVBoxLayout()
self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.setContentsMargins(0, 0, 0, 0)
@ -991,7 +988,7 @@ title="{}" {}>{}</button>""".format(
def raiseMain(self) -> bool: def raiseMain(self) -> bool:
if not self.app.activeWindow(): if not self.app.activeWindow():
# make sure window is shown # make sure window is shown
self.setWindowState(self.windowState() & ~Qt.WindowMinimized) # type: ignore self.setWindowState(self.windowState() & ~Qt.WindowState.WindowMinimized) # type: ignore
return True return True
def setupStyle(self) -> None: def setupStyle(self) -> None:
@ -1393,7 +1390,7 @@ title="{}" {}>{}</button>""".format(
frm.setupUi(d) frm.setupUi(d)
restoreGeom(d, "DebugConsoleWindow") restoreGeom(d, "DebugConsoleWindow")
restoreSplitter(frm.splitter, "DebugConsoleWindow") restoreSplitter(frm.splitter, "DebugConsoleWindow")
font = QFontDatabase.systemFont(QFontDatabase.FixedFont) font = QFontDatabase.systemFont(QFontDatabase.SystemFont.FixedFont)
font.setPointSize(frm.text.font().pointSize() + 1) font.setPointSize(frm.text.font().pointSize() + 1)
frm.text.setFont(font) frm.text.setFont(font)
frm.log.setFont(font) frm.log.setFont(font)
@ -1485,7 +1482,7 @@ title="{}" {}>{}</button>""".format(
def onDebugPrint(self, frm: aqt.forms.debug.Ui_Dialog) -> None: def onDebugPrint(self, frm: aqt.forms.debug.Ui_Dialog) -> None:
cursor = frm.text.textCursor() cursor = frm.text.textCursor()
position = cursor.position() position = cursor.position()
cursor.select(QTextCursor.LineUnderCursor) cursor.select(QTextCursor.SelectionType.LineUnderCursor)
line = cursor.selectedText() line = cursor.selectedText()
pfx, sfx = "pp(", ")" pfx, sfx = "pp(", ")"
if not line.startswith(pfx): if not line.startswith(pfx):
@ -1566,7 +1563,7 @@ title="{}" {}>{}</button>""".format(
cast(QAction, action).setStatusTip("") cast(QAction, action).setStatusTip("")
def onMacMinimize(self) -> None: def onMacMinimize(self) -> None:
self.setWindowState(self.windowState() | Qt.WindowMinimized) # type: ignore self.setWindowState(self.windowState() | Qt.WindowState.WindowMinimized) # type: ignore
# Single instance support # Single instance support
########################################################################## ##########################################################################
@ -1606,7 +1603,7 @@ title="{}" {}>{}</button>""".format(
if isWin: if isWin:
# on windows we can raise the window by minimizing and restoring # on windows we can raise the window by minimizing and restoring
self.showMinimized() self.showMinimized()
self.setWindowState(Qt.WindowActive) self.setWindowState(Qt.WindowState.WindowActive)
self.showNormal() self.showNormal()
else: else:
# on osx we can raise the window. on unity the icon in the tray will just flash. # on osx we can raise the window. on unity the icon in the tray will just flash.

View file

@ -105,33 +105,33 @@ class MediaChecker:
text = QPlainTextEdit() text = QPlainTextEdit()
text.setReadOnly(True) text.setReadOnly(True)
text.setPlainText(report) text.setPlainText(report)
text.setWordWrapMode(QTextOption.NoWrap) text.setWordWrapMode(QTextOption.WrapMode.NoWrap)
layout.addWidget(text) layout.addWidget(text)
box = QDialogButtonBox(QDialogButtonBox.Close) box = QDialogButtonBox(QDialogButtonBox.StandardButton.Close)
layout.addWidget(box) layout.addWidget(box)
if output.unused: if output.unused:
b = QPushButton(tr.media_check_delete_unused()) b = QPushButton(tr.media_check_delete_unused())
b.setAutoDefault(False) b.setAutoDefault(False)
box.addButton(b, QDialogButtonBox.RejectRole) box.addButton(b, QDialogButtonBox.ButtonRole.RejectRole)
qconnect(b.clicked, lambda c: self._on_trash_files(output.unused)) qconnect(b.clicked, lambda c: self._on_trash_files(output.unused))
if output.missing: if output.missing:
if any(map(lambda x: x.startswith("latex-"), output.missing)): if any(map(lambda x: x.startswith("latex-"), output.missing)):
b = QPushButton(tr.media_check_render_latex()) b = QPushButton(tr.media_check_render_latex())
b.setAutoDefault(False) b.setAutoDefault(False)
box.addButton(b, QDialogButtonBox.RejectRole) box.addButton(b, QDialogButtonBox.ButtonRole.RejectRole)
qconnect(b.clicked, self._on_render_latex) qconnect(b.clicked, self._on_render_latex)
if output.have_trash: if output.have_trash:
b = QPushButton(tr.media_check_empty_trash()) b = QPushButton(tr.media_check_empty_trash())
b.setAutoDefault(False) b.setAutoDefault(False)
box.addButton(b, QDialogButtonBox.RejectRole) box.addButton(b, QDialogButtonBox.ButtonRole.RejectRole)
qconnect(b.clicked, lambda c: self._on_empty_trash()) qconnect(b.clicked, lambda c: self._on_empty_trash())
b = QPushButton(tr.media_check_restore_trash()) b = QPushButton(tr.media_check_restore_trash())
b.setAutoDefault(False) b.setAutoDefault(False)
box.addButton(b, QDialogButtonBox.RejectRole) box.addButton(b, QDialogButtonBox.ButtonRole.RejectRole)
qconnect(b.clicked, lambda c: self._on_restore_trash()) qconnect(b.clicked, lambda c: self._on_restore_trash())
qconnect(box.rejected, diag.reject) qconnect(box.rejected, diag.reject)

View file

@ -162,7 +162,9 @@ class MediaSyncDialog(QDialog):
self.abort_button = QPushButton(tr.sync_abort_button()) self.abort_button = QPushButton(tr.sync_abort_button())
qconnect(self.abort_button.clicked, self._on_abort) qconnect(self.abort_button.clicked, self._on_abort)
self.abort_button.setAutoDefault(False) self.abort_button.setAutoDefault(False)
self.form.buttonBox.addButton(self.abort_button, QDialogButtonBox.ActionRole) self.form.buttonBox.addButton(
self.abort_button, QDialogButtonBox.ButtonRole.ActionRole
)
self.abort_button.setHidden(not self._syncer.is_syncing()) self.abort_button.setHidden(not self._syncer.is_syncing())
gui_hooks.media_sync_did_progress.append(self._on_log_entry) gui_hooks.media_sync_did_progress.append(self._on_log_entry)
@ -171,7 +173,7 @@ class MediaSyncDialog(QDialog):
self.form.plainTextEdit.setPlainText( self.form.plainTextEdit.setPlainText(
"\n".join(self._entry_to_text(x) for x in syncer.entries()) "\n".join(self._entry_to_text(x) for x in syncer.entries())
) )
self.form.plainTextEdit.moveCursor(QTextCursor.End) self.form.plainTextEdit.moveCursor(QTextCursor.MoveOperation.End)
self.show() self.show()
def reject(self) -> None: def reject(self) -> None:

View file

@ -48,7 +48,7 @@ class Models(QDialog):
parent = parent or mw parent = parent or mw
self.fromMain = fromMain self.fromMain = fromMain
self.selected_notetype_id = selected_notetype_id self.selected_notetype_id = selected_notetype_id
QDialog.__init__(self, parent, Qt.Window) QDialog.__init__(self, parent, Qt.WindowType.Window)
self.col = mw.col.weakref() self.col = mw.col.weakref()
assert self.col assert self.col
self.mm = self.col.models self.mm = self.col.models
@ -97,7 +97,7 @@ class Models(QDialog):
default_buttons.append((tr.notetypes_options(), self.onAdvanced)) default_buttons.append((tr.notetypes_options(), self.onAdvanced))
for label, func in gui_hooks.models_did_init_buttons(default_buttons, self): for label, func in gui_hooks.models_did_init_buttons(default_buttons, self):
button = box.addButton(label, QDialogButtonBox.ActionRole) button = box.addButton(label, QDialogButtonBox.ButtonRole.ActionRole)
qconnect(button.clicked, func) qconnect(button.clicked, func)
qconnect(f.modelsList.itemDoubleClicked, self.onRename) qconnect(f.modelsList.itemDoubleClicked, self.onRename)
@ -235,7 +235,7 @@ class AddModel(QDialog):
self.parent_ = parent or mw self.parent_ = parent or mw
self.mw = mw self.mw = mw
self.col = mw.col self.col = mw.col
QDialog.__init__(self, self.parent_, Qt.Window) QDialog.__init__(self, self.parent_, Qt.WindowType.Window)
self.model = None self.model = None
self.dialog = aqt.forms.addmodel.Ui_Dialog() self.dialog = aqt.forms.addmodel.Ui_Dialog()
self.dialog.setupUi(self) self.dialog.setupUi(self)

View file

@ -93,7 +93,7 @@ def reposition_new_cards_dialog(
d = QDialog(parent) d = QDialog(parent)
disable_help_button(d) disable_help_button(d)
d.setWindowModality(Qt.WindowModal) d.setWindowModality(Qt.WindowModality.WindowModal)
frm = aqt.forms.reposition.Ui_Dialog() frm = aqt.forms.reposition.Ui_Dialog()
frm.setupUi(d) frm.setupUi(d)

View file

@ -16,14 +16,18 @@ from aqt.utils import HelpPage, disable_help_button, openHelp, showInfo, showWar
class Preferences(QDialog): class Preferences(QDialog):
def __init__(self, mw: AnkiQt) -> None: def __init__(self, mw: AnkiQt) -> None:
QDialog.__init__(self, mw, Qt.Window) QDialog.__init__(self, mw, Qt.WindowType.Window)
self.mw = mw self.mw = mw
self.prof = self.mw.pm.profile self.prof = self.mw.pm.profile
self.form = aqt.forms.preferences.Ui_Preferences() self.form = aqt.forms.preferences.Ui_Preferences()
self.form.setupUi(self) self.form.setupUi(self)
disable_help_button(self) disable_help_button(self)
self.form.buttonBox.button(QDialogButtonBox.Help).setAutoDefault(False) self.form.buttonBox.button(QDialogButtonBox.StandardButton.Help).setAutoDefault(
self.form.buttonBox.button(QDialogButtonBox.Close).setAutoDefault(False) False
)
self.form.buttonBox.button(
QDialogButtonBox.StandardButton.Close
).setAutoDefault(False)
qconnect( qconnect(
self.form.buttonBox.helpRequested, lambda: openHelp(HelpPage.PREFERENCES) self.form.buttonBox.helpRequested, lambda: openHelp(HelpPage.PREFERENCES)
) )

View file

@ -461,9 +461,9 @@ create table if not exists profiles
code = obj[1] code = obj[1]
name = obj[0] name = obj[0]
r = QMessageBox.question( r = QMessageBox.question(
None, "Anki", tr.profiles_confirm_lang_choice(lang=name), QMessageBox.Yes | QMessageBox.No, QMessageBox.No # type: ignore None, "Anki", tr.profiles_confirm_lang_choice(lang=name), QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, QMessageBox.StandardButton.No # type: ignore
) )
if r != QMessageBox.Yes: if r != QMessageBox.StandardButton.Yes:
return self.setDefaultLang(f.lang.currentRow()) return self.setDefaultLang(f.lang.currentRow())
self.setLang(code) self.setLang(code)

View file

@ -92,7 +92,7 @@ class ProgressManager:
self._win.form.progressBar.setTextVisible(False) self._win.form.progressBar.setTextVisible(False)
self._win.form.label.setText(label) self._win.form.label.setText(label)
self._win.setWindowTitle("Anki") self._win.setWindowTitle("Anki")
self._win.setWindowModality(Qt.ApplicationModal) self._win.setWindowModality(Qt.WindowModality.ApplicationModal)
self._win.setMinimumWidth(300) self._win.setMinimumWidth(300)
self._busy_cursor_timer = QTimer(self.mw) self._busy_cursor_timer = QTimer(self.mw)
self._busy_cursor_timer.setSingleShot(True) self._busy_cursor_timer.setSingleShot(True)
@ -177,7 +177,7 @@ class ProgressManager:
elap = time.time() - self._shown elap = time.time() - self._shown
if elap >= 0.5: if elap >= 0.5:
break break
self.app.processEvents(QEventLoop.ExcludeUserInputEvents) # type: ignore #possibly related to https://github.com/python/mypy/issues/6910 self.app.processEvents(QEventLoop.ProcessEventsFlag.ExcludeUserInputEvents) # type: ignore #possibly related to https://github.com/python/mypy/issues/6910
# if the parent window has been deleted, the progress dialog may have # if the parent window has been deleted, the progress dialog may have
# already been dropped; delete it if it hasn't been # already been dropped; delete it if it hasn't been
if not sip.isdeleted(self._win): if not sip.isdeleted(self._win):
@ -186,7 +186,7 @@ class ProgressManager:
self._shown = 0 self._shown = 0
def _set_busy_cursor(self) -> None: def _set_busy_cursor(self) -> None:
self.mw.app.setOverrideCursor(QCursor(Qt.WaitCursor)) self.mw.app.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
def _restore_cursor(self) -> None: def _restore_cursor(self) -> None:
self.app.restoreOverrideCursor() self.app.restoreOverrideCursor()
@ -235,6 +235,6 @@ class ProgressDialog(QDialog):
evt.ignore() evt.ignore()
def keyPressEvent(self, evt: QKeyEvent) -> None: def keyPressEvent(self, evt: QKeyEvent) -> None:
if evt.key() == Qt.Key_Escape: if evt.key() == Qt.Key.Key_Escape:
evt.ignore() evt.ignore()
self.wantCancel = True self.wantCancel = True

View file

@ -9,14 +9,34 @@ import sys
import traceback import traceback
from typing import Callable, Union from typing import Callable, Union
from PyQt5.Qt import * # type: ignore try:
from PyQt5.QtCore import * from PyQt6 import sip
from PyQt5.QtCore import pyqtRemoveInputHook # pylint: disable=no-name-in-module from PyQt6.QtCore import *
from PyQt5.QtGui import * # type: ignore
from PyQt5.QtNetwork import QLocalServer, QLocalSocket, QNetworkProxy # conflicting Qt and qFuzzyCompare definitions require an ignore
from PyQt5.QtWebChannel import QWebChannel from PyQt6.QtGui import * # type: ignore[misc]
from PyQt5.QtWebEngineWidgets import * from PyQt6.QtNetwork import QLocalServer, QLocalSocket, QNetworkProxy
from PyQt5.QtWidgets import * from PyQt6.QtWebChannel import QWebChannel
from PyQt6.QtWebEngineCore import *
from PyQt6.QtWebEngineWidgets import *
from PyQt6.QtWidgets import *
except:
from PyQt5.QtCore import * # type: ignore
from PyQt5.QtGui import * # type: ignore
from PyQt5.QtNetwork import ( # type: ignore
QLocalServer,
QLocalSocket,
QNetworkProxy,
)
from PyQt5.QtWebChannel import QWebChannel # type: ignore
from PyQt5.QtWebEngineCore import * # type: ignore
from PyQt5.QtWebEngineWidgets import * # type: ignore
from PyQt5.QtWidgets import * # type: ignore
try:
from PyQt5 import sip # type: ignore
except ImportError:
import sip # type: ignore
from anki.utils import isMac, isWin from anki.utils import isMac, isWin
@ -24,12 +44,6 @@ from anki.utils import isMac, isWin
os.environ["LIBOVERLAY_SCROLLBAR"] = "0" os.environ["LIBOVERLAY_SCROLLBAR"] = "0"
try:
from PyQt5 import sip
except ImportError:
import sip # type: ignore
def debug() -> None: def debug() -> None:
from pdb import set_trace from pdb import set_trace

View file

@ -1,6 +1,8 @@
# Copyright: Ankitects Pty Ltd and contributors # Copyright: Ankitects Pty Ltd and contributors
# 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
# pylint: skip-file
""" """
PyQt5-only code PyQt5-only code
""" """

View file

@ -433,11 +433,11 @@ class Reviewer:
return [ return [
("e", self.mw.onEditCurrent), ("e", self.mw.onEditCurrent),
(" ", self.onEnterKey), (" ", self.onEnterKey),
(Qt.Key_Return, self.onEnterKey), (Qt.Key.Key_Return, self.onEnterKey),
(Qt.Key_Enter, self.onEnterKey), (Qt.Key.Key_Enter, self.onEnterKey),
("m", self.showContextMenu), ("m", self.showContextMenu),
("r", self.replayAudio), ("r", self.replayAudio),
(Qt.Key_F5, self.replayAudio), (Qt.Key.Key_F5, self.replayAudio),
*( *(
(f"Ctrl+{flag.index}", self.set_flag_func(flag.index)) (f"Ctrl+{flag.index}", self.set_flag_func(flag.index))
for flag in self.mw.flags.all() for flag in self.mw.flags.all()
@ -875,7 +875,7 @@ time = %(time)d;
part2 = tr.studying_minute(count=mins) part2 = tr.studying_minute(count=mins)
fin = tr.studying_finish() fin = tr.studying_finish()
diag = askUserDialog(f"{part1} {part2}", [tr.studying_continue(), fin]) diag = askUserDialog(f"{part1} {part2}", [tr.studying_continue(), fin])
diag.setIcon(QMessageBox.Information) diag.setIcon(QMessageBox.Icon.Information)
if diag.run() == fin: if diag.run() == fin:
self.mw.moveToState("deckBrowser") self.mw.moveToState("deckBrowser")
return True return True

View file

@ -666,15 +666,18 @@ class RecordDialog(QDialog):
hbox.addWidget(self.label) hbox.addWidget(self.label)
v = QVBoxLayout() v = QVBoxLayout()
v.addLayout(hbox) v.addLayout(hbox)
buts = QDialogButtonBox.Save | QDialogButtonBox.Cancel buts = (
QDialogButtonBox.StandardButton.Save
| QDialogButtonBox.StandardButton.Cancel
)
b = QDialogButtonBox(buts) # type: ignore b = QDialogButtonBox(buts) # type: ignore
v.addWidget(b) v.addWidget(b)
self.setLayout(v) self.setLayout(v)
save_button = b.button(QDialogButtonBox.Save) save_button = b.button(QDialogButtonBox.StandardButton.Save)
save_button.setDefault(True) save_button.setDefault(True)
save_button.setAutoDefault(True) save_button.setAutoDefault(True)
qconnect(save_button.clicked, self.accept) qconnect(save_button.clicked, self.accept)
cancel_button = b.button(QDialogButtonBox.Cancel) cancel_button = b.button(QDialogButtonBox.StandardButton.Cancel)
cancel_button.setDefault(False) cancel_button.setDefault(False)
cancel_button.setAutoDefault(False) cancel_button.setAutoDefault(False)
qconnect(cancel_button.clicked, self.reject) qconnect(cancel_button.clicked, self.reject)

View file

@ -25,7 +25,7 @@ class NewDeckStats(QDialog):
"""New deck stats.""" """New deck stats."""
def __init__(self, mw: aqt.main.AnkiQt) -> None: def __init__(self, mw: aqt.main.AnkiQt) -> None:
QDialog.__init__(self, mw, Qt.Window) QDialog.__init__(self, mw, Qt.WindowType.Window)
mw.garbage_collect_on_dialog_finish(self) mw.garbage_collect_on_dialog_finish(self)
self.mw = mw self.mw = mw
self.name = "deckStats" self.name = "deckStats"
@ -40,7 +40,9 @@ class NewDeckStats(QDialog):
f.groupBox.setVisible(False) f.groupBox.setVisible(False)
f.groupBox_2.setVisible(False) f.groupBox_2.setVisible(False)
restoreGeom(self, self.name) restoreGeom(self, self.name)
b = f.buttonBox.addButton(tr.statistics_save_pdf(), QDialogButtonBox.ActionRole) b = f.buttonBox.addButton(
tr.statistics_save_pdf(), QDialogButtonBox.ButtonRole.ActionRole
)
qconnect(b.clicked, self.saveImage) qconnect(b.clicked, self.saveImage)
b.setAutoDefault(False) b.setAutoDefault(False)
maybeHideClose(self.form.buttonBox) maybeHideClose(self.form.buttonBox)
@ -104,7 +106,7 @@ class DeckStats(QDialog):
"""Legacy deck stats, used by some add-ons.""" """Legacy deck stats, used by some add-ons."""
def __init__(self, mw: aqt.main.AnkiQt) -> None: def __init__(self, mw: aqt.main.AnkiQt) -> None:
QDialog.__init__(self, mw, Qt.Window) QDialog.__init__(self, mw, Qt.WindowType.Window)
mw.garbage_collect_on_dialog_finish(self) mw.garbage_collect_on_dialog_finish(self)
self.mw = mw self.mw = mw
self.name = "deckStats" self.name = "deckStats"
@ -123,7 +125,9 @@ class DeckStats(QDialog):
self.setStyleSheet("QGroupBox { border: 0; }") self.setStyleSheet("QGroupBox { border: 0; }")
f.setupUi(self) f.setupUi(self)
restoreGeom(self, self.name) restoreGeom(self, self.name)
b = f.buttonBox.addButton(tr.statistics_save_pdf(), QDialogButtonBox.ActionRole) b = f.buttonBox.addButton(
tr.statistics_save_pdf(), QDialogButtonBox.ButtonRole.ActionRole
)
qconnect(b.clicked, self.saveImage) qconnect(b.clicked, self.saveImage)
b.setAutoDefault(False) b.setAutoDefault(False)
qconnect(f.groups.clicked, lambda: self.changeScope("deck")) qconnect(f.groups.clicked, lambda: self.changeScope("deck"))

View file

@ -49,18 +49,18 @@ class StudyDeck(QDialog):
disable_help_button(self) disable_help_button(self)
if not cancel: if not cancel:
self.form.buttonBox.removeButton( self.form.buttonBox.removeButton(
self.form.buttonBox.button(QDialogButtonBox.Cancel) self.form.buttonBox.button(QDialogButtonBox.StandardButton.Cancel)
) )
if buttons is not None: if buttons is not None:
for button_or_label in buttons: for button_or_label in buttons:
self.form.buttonBox.addButton( self.form.buttonBox.addButton(
button_or_label, QDialogButtonBox.ActionRole button_or_label, QDialogButtonBox.ButtonRole.ActionRole
) )
else: else:
b = QPushButton(tr.actions_add()) b = QPushButton(tr.actions_add())
b.setShortcut(QKeySequence("Ctrl+N")) b.setShortcut(QKeySequence("Ctrl+N"))
b.setToolTip(shortcut(tr.decks_add_new_deck_ctrlandn())) b.setToolTip(shortcut(tr.decks_add_new_deck_ctrlandn()))
self.form.buttonBox.addButton(b, QDialogButtonBox.ActionRole) self.form.buttonBox.addButton(b, QDialogButtonBox.ButtonRole.ActionRole)
qconnect(b.clicked, self.onAddDeck) qconnect(b.clicked, self.onAddDeck)
if title: if title:
self.setWindowTitle(title) self.setWindowTitle(title)
@ -78,9 +78,9 @@ class StudyDeck(QDialog):
self.origNames = names() self.origNames = names()
self.name: Optional[str] = None self.name: Optional[str] = None
self.ok = self.form.buttonBox.addButton( self.ok = self.form.buttonBox.addButton(
accept or tr.decks_study(), QDialogButtonBox.AcceptRole accept or tr.decks_study(), QDialogButtonBox.ButtonRole.AcceptRole
) )
self.setWindowModality(Qt.WindowModal) self.setWindowModality(Qt.WindowModality.WindowModal)
qconnect(self.form.buttonBox.helpRequested, lambda: openHelp(help)) qconnect(self.form.buttonBox.helpRequested, lambda: openHelp(help))
qconnect(self.form.filter.textEdited, self.redraw) qconnect(self.form.filter.textEdited, self.redraw)
qconnect(self.form.list.itemDoubleClicked, self.accept) qconnect(self.form.list.itemDoubleClicked, self.accept)
@ -90,20 +90,20 @@ class StudyDeck(QDialog):
self.exec() self.exec()
def eventFilter(self, obj: QObject, evt: QEvent) -> bool: def eventFilter(self, obj: QObject, evt: QEvent) -> bool:
if isinstance(evt, QKeyEvent) and evt.type() == QEvent.KeyPress: if isinstance(evt, QKeyEvent) and evt.type() == QEvent.Type.KeyPress:
new_row = current_row = self.form.list.currentRow() new_row = current_row = self.form.list.currentRow()
rows_count = self.form.list.count() rows_count = self.form.list.count()
key = evt.key() key = evt.key()
if key == Qt.Key_Up: if key == Qt.Key.Key_Up:
new_row = current_row - 1 new_row = current_row - 1
elif key == Qt.Key_Down: elif key == Qt.Key.Key_Down:
new_row = current_row + 1 new_row = current_row + 1
elif ( elif (
int(evt.modifiers()) & Qt.ControlModifier evt.modifiers() & Qt.KeyboardModifier.ControlModifier
and Qt.Key_1 <= key <= Qt.Key_9 and Qt.Key.Key_1 <= key <= Qt.Key.Key_9
): ):
row_index = key - Qt.Key_1 row_index = key - Qt.Key.Key_1
if row_index < rows_count: if row_index < rows_count:
new_row = row_index new_row = row_index
@ -126,7 +126,7 @@ class StudyDeck(QDialog):
else: else:
idx = 0 idx = 0
l.setCurrentRow(idx) l.setCurrentRow(idx)
l.scrollToItem(l.item(idx), QAbstractItemView.PositionAtCenter) l.scrollToItem(l.item(idx), QAbstractItemView.ScrollHint.PositionAtCenter)
def _matches(self, name: str, filt: str) -> bool: def _matches(self, name: str, filt: str) -> bool:
name = name.lower() name = name.lower()

View file

@ -28,7 +28,7 @@ class Switch(QAbstractButton):
super().__init__(parent=parent) super().__init__(parent=parent)
self.setCheckable(True) self.setCheckable(True)
super().setChecked(False) super().setChecked(False)
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
self._left_label = left_label self._left_label = left_label
self._right_label = right_label self._right_label = right_label
self._left_color = left_color self._left_color = left_color
@ -76,8 +76,8 @@ class Switch(QAbstractButton):
def paintEvent(self, _event: QPaintEvent) -> None: def paintEvent(self, _event: QPaintEvent) -> None:
painter = QPainter(self) painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing, True) painter.setRenderHint(QPainter.RenderHint.Antialiasing, True)
painter.setPen(Qt.NoPen) painter.setPen(Qt.PenStyle.NoPen)
self._paint_path(painter) self._paint_path(painter)
self._paint_knob(painter) self._paint_knob(painter)
self._paint_label(painter) self._paint_label(painter)
@ -113,15 +113,17 @@ class Switch(QAbstractButton):
font = painter.font() font = painter.font()
font.setPixelSize(int(1.2 * self._knob_radius)) font.setPixelSize(int(1.2 * self._knob_radius))
painter.setFont(font) painter.setFont(font)
painter.drawText(self._current_knob_rectangle(), Qt.AlignCenter, self.label) painter.drawText(
self._current_knob_rectangle(), Qt.AlignmentFlag.AlignCenter, self.label
)
def mouseReleaseEvent(self, event: QMouseEvent) -> None: def mouseReleaseEvent(self, event: QMouseEvent) -> None:
super().mouseReleaseEvent(event) super().mouseReleaseEvent(event)
if event.button() == Qt.LeftButton: if event.button() == Qt.MouseButton.LeftButton:
self._animate_toggle() self._animate_toggle()
def enterEvent(self, event: QEvent) -> None: def enterEvent(self, event: QEnterEvent) -> None:
self.setCursor(Qt.PointingHandCursor) self.setCursor(Qt.CursorShape.PointingHandCursor)
super().enterEvent(event) super().enterEvent(event)
def toggle(self) -> None: def toggle(self) -> None:

View file

@ -292,7 +292,7 @@ def get_id_and_pass_from_user(
diag = QDialog(mw) diag = QDialog(mw)
diag.setWindowTitle("Anki") diag.setWindowTitle("Anki")
disable_help_button(diag) disable_help_button(diag)
diag.setWindowModality(Qt.WindowModal) diag.setWindowModality(Qt.WindowModality.WindowModal)
vbox = QVBoxLayout() vbox = QVBoxLayout()
info_label = QLabel( info_label = QLabel(
without_unicode_isolation( without_unicode_isolation(
@ -313,11 +313,11 @@ def get_id_and_pass_from_user(
g.addWidget(l2, 1, 0) g.addWidget(l2, 1, 0)
passwd = QLineEdit() passwd = QLineEdit()
passwd.setText(password) passwd.setText(password)
passwd.setEchoMode(QLineEdit.Password) passwd.setEchoMode(QLineEdit.EchoMode.Password)
g.addWidget(passwd, 1, 1) g.addWidget(passwd, 1, 1)
vbox.addLayout(g) vbox.addLayout(g)
bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) # type: ignore bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) # type: ignore
bb.button(QDialogButtonBox.Ok).setAutoDefault(True) bb.button(QDialogButtonBox.StandardButton.Ok).setAutoDefault(True)
qconnect(bb.accepted, diag.accept) qconnect(bb.accepted, diag.accept)
qconnect(bb.rejected, diag.reject) qconnect(bb.rejected, diag.reject)
vbox.addWidget(bb) vbox.addWidget(bb)

View file

@ -26,9 +26,9 @@ class TagEdit(QLineEdit):
self._completer = TagCompleter(self.model, parent, self) self._completer = TagCompleter(self.model, parent, self)
else: else:
self._completer = QCompleter(self.model, parent) self._completer = QCompleter(self.model, parent)
self._completer.setCompletionMode(QCompleter.PopupCompletion) self._completer.setCompletionMode(QCompleter.CompletionMode.PopupCompletion)
self._completer.setCaseSensitivity(Qt.CaseInsensitive) self._completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
self._completer.setFilterMode(Qt.MatchContains) self._completer.setFilterMode(Qt.MatchFlag.MatchContains)
self.setCompleter(self._completer) self.setCompleter(self._completer)
def setCol(self, col: Collection) -> None: def setCol(self, col: Collection) -> None:
@ -45,12 +45,15 @@ class TagEdit(QLineEdit):
QLineEdit.focusInEvent(self, evt) QLineEdit.focusInEvent(self, evt)
def keyPressEvent(self, evt: QKeyEvent) -> None: def keyPressEvent(self, evt: QKeyEvent) -> None:
if evt.key() in (Qt.Key_Up, Qt.Key_Down): if evt.key() in (Qt.Key.Key_Up, Qt.Key.Key_Down):
# show completer on arrow key up/down # show completer on arrow key up/down
if not self._completer.popup().isVisible(): if not self._completer.popup().isVisible():
self.showCompleter() self.showCompleter()
return return
if evt.key() == Qt.Key_Tab and int(evt.modifiers()) & Qt.ControlModifier: if (
evt.key() == Qt.Key.Key_Tab
and evt.modifiers() & Qt.KeyboardModifier.ControlModifier
):
# select next completion # select next completion
if not self._completer.popup().isVisible(): if not self._completer.popup().isVisible():
self.showCompleter() self.showCompleter()
@ -61,7 +64,7 @@ class TagEdit(QLineEdit):
self._completer.setCurrentRow(0) self._completer.setCurrentRow(0)
return return
if ( if (
evt.key() in (Qt.Key_Enter, Qt.Key_Return) evt.key() in (Qt.Key.Key_Enter, Qt.Key.Key_Return)
and self._completer.popup().isVisible() and self._completer.popup().isVisible()
): ):
# apply first completion if no suggestion selected # apply first completion if no suggestion selected
@ -78,13 +81,13 @@ class TagEdit(QLineEdit):
# if it's a modifier, don't show # if it's a modifier, don't show
return return
if evt.key() not in ( if evt.key() not in (
Qt.Key_Enter, Qt.Key.Key_Enter,
Qt.Key_Return, Qt.Key.Key_Return,
Qt.Key_Escape, Qt.Key.Key_Escape,
Qt.Key_Space, Qt.Key.Key_Space,
Qt.Key_Tab, Qt.Key.Key_Tab,
Qt.Key_Backspace, Qt.Key.Key_Backspace,
Qt.Key_Delete, Qt.Key.Key_Delete,
): ):
self.showCompleter() self.showCompleter()
gui_hooks.tag_editor_did_process_key(self, evt) gui_hooks.tag_editor_did_process_key(self, evt)

View file

@ -13,7 +13,7 @@ from aqt.utils import disable_help_button, restoreGeom, saveGeom, showWarning, t
class TagLimit(QDialog): class TagLimit(QDialog):
def __init__(self, mw: AnkiQt, parent: CustomStudy) -> None: def __init__(self, mw: AnkiQt, parent: CustomStudy) -> None:
QDialog.__init__(self, parent, Qt.Window) QDialog.__init__(self, parent, Qt.WindowType.Window)
self.tags: str = "" self.tags: str = ""
self.tags_list: list[str] = [] self.tags_list: list[str] = []
self.mw = mw self.mw = mw
@ -23,11 +23,15 @@ class TagLimit(QDialog):
self.dialog.setupUi(self) self.dialog.setupUi(self)
disable_help_button(self) disable_help_button(self)
s = QShortcut( s = QShortcut(
QKeySequence("ctrl+d"), self.dialog.activeList, context=Qt.WidgetShortcut QKeySequence("ctrl+d"),
self.dialog.activeList,
context=Qt.ShortcutContext.WidgetShortcut,
) )
qconnect(s.activated, self.dialog.activeList.clearSelection) qconnect(s.activated, self.dialog.activeList.clearSelection)
s = QShortcut( s = QShortcut(
QKeySequence("ctrl+d"), self.dialog.inactiveList, context=Qt.WidgetShortcut QKeySequence("ctrl+d"),
self.dialog.inactiveList,
context=Qt.ShortcutContext.WidgetShortcut,
) )
qconnect(s.activated, self.dialog.inactiveList.clearSelection) qconnect(s.activated, self.dialog.inactiveList.clearSelection)
self.rebuildTagList() self.rebuildTagList()
@ -54,19 +58,19 @@ class TagLimit(QDialog):
item = QListWidgetItem(t.replace("_", " ")) item = QListWidgetItem(t.replace("_", " "))
self.dialog.activeList.addItem(item) self.dialog.activeList.addItem(item)
if t in yesHash: if t in yesHash:
mode = QItemSelectionModel.Select mode = QItemSelectionModel.SelectionFlag.Select
self.dialog.activeCheck.setChecked(True) self.dialog.activeCheck.setChecked(True)
else: else:
mode = QItemSelectionModel.Deselect mode = QItemSelectionModel.SelectionFlag.Deselect
idx = self.dialog.activeList.indexFromItem(item) idx = self.dialog.activeList.indexFromItem(item)
self.dialog.activeList.selectionModel().select(idx, mode) self.dialog.activeList.selectionModel().select(idx, mode)
# inactive # inactive
item = QListWidgetItem(t.replace("_", " ")) item = QListWidgetItem(t.replace("_", " "))
self.dialog.inactiveList.addItem(item) self.dialog.inactiveList.addItem(item)
if t in noHash: if t in noHash:
mode = QItemSelectionModel.Select mode = QItemSelectionModel.SelectionFlag.Select
else: else:
mode = QItemSelectionModel.Deselect mode = QItemSelectionModel.SelectionFlag.Deselect
idx = self.dialog.inactiveList.indexFromItem(item) idx = self.dialog.inactiveList.indexFromItem(item)
self.dialog.inactiveList.selectionModel().select(idx, mode) self.dialog.inactiveList.selectionModel().select(idx, mode)

View file

@ -92,7 +92,9 @@ class ThemeManager:
icon = QIcon(path.path) icon = QIcon(path.path)
pixmap = icon.pixmap(16) pixmap = icon.pixmap(16)
painter = QPainter(pixmap) painter = QPainter(pixmap)
painter.setCompositionMode(QPainter.CompositionMode_SourceIn) painter.setCompositionMode(
QPainter.CompositionMode.CompositionMode_SourceIn
)
painter.fillRect(pixmap.rect(), QColor(path.current_color(self.night_mode))) painter.fillRect(pixmap.rect(), QColor(path.current_color(self.night_mode)))
painter.end() painter.end()
icon = QIcon(pixmap) icon = QIcon(pixmap)
@ -207,34 +209,44 @@ QTabWidget {{ background-color: {}; }}
palette = QPalette() palette = QPalette()
text_fg = self.qcolor(colors.TEXT_FG) text_fg = self.qcolor(colors.TEXT_FG)
palette.setColor(QPalette.WindowText, text_fg) palette.setColor(QPalette.ColorRole.WindowText, text_fg)
palette.setColor(QPalette.ToolTipText, text_fg) palette.setColor(QPalette.ColorRole.ToolTipText, text_fg)
palette.setColor(QPalette.Text, text_fg) palette.setColor(QPalette.ColorRole.Text, text_fg)
palette.setColor(QPalette.ButtonText, text_fg) palette.setColor(QPalette.ColorRole.ButtonText, text_fg)
hlbg = self.qcolor(colors.HIGHLIGHT_BG) hlbg = self.qcolor(colors.HIGHLIGHT_BG)
hlbg.setAlpha(64) hlbg.setAlpha(64)
palette.setColor(QPalette.HighlightedText, self.qcolor(colors.HIGHLIGHT_FG)) palette.setColor(
palette.setColor(QPalette.Highlight, hlbg) QPalette.ColorRole.HighlightedText, self.qcolor(colors.HIGHLIGHT_FG)
)
palette.setColor(QPalette.ColorRole.Highlight, hlbg)
window_bg = self.qcolor(colors.WINDOW_BG) window_bg = self.qcolor(colors.WINDOW_BG)
palette.setColor(QPalette.Window, window_bg) palette.setColor(QPalette.ColorRole.Window, window_bg)
palette.setColor(QPalette.AlternateBase, window_bg) palette.setColor(QPalette.ColorRole.AlternateBase, window_bg)
palette.setColor(QPalette.Button, QColor("#454545")) palette.setColor(QPalette.ColorRole.Button, QColor("#454545"))
frame_bg = self.qcolor(colors.FRAME_BG) frame_bg = self.qcolor(colors.FRAME_BG)
palette.setColor(QPalette.Base, frame_bg) palette.setColor(QPalette.ColorRole.Base, frame_bg)
palette.setColor(QPalette.ToolTipBase, frame_bg) palette.setColor(QPalette.ColorRole.ToolTipBase, frame_bg)
disabled_color = self.qcolor(colors.DISABLED) disabled_color = self.qcolor(colors.DISABLED)
palette.setColor(QPalette.Disabled, QPalette.Text, disabled_color) palette.setColor(
palette.setColor(QPalette.Disabled, QPalette.ButtonText, disabled_color) QPalette.ColorGroup.Disabled, QPalette.ColorRole.Text, disabled_color
palette.setColor(QPalette.Disabled, QPalette.HighlightedText, disabled_color) )
palette.setColor(
QPalette.ColorGroup.Disabled, QPalette.ColorRole.ButtonText, disabled_color
)
palette.setColor(
QPalette.ColorGroup.Disabled,
QPalette.ColorRole.HighlightedText,
disabled_color,
)
palette.setColor(QPalette.Link, self.qcolor(colors.LINK)) palette.setColor(QPalette.ColorRole.Link, self.qcolor(colors.LINK))
palette.setColor(QPalette.BrightText, Qt.red) palette.setColor(QPalette.ColorRole.BrightText, Qt.GlobalColor.red)
app.setPalette(palette) app.setPalette(palette)

View file

@ -59,17 +59,17 @@ class LatestVersionFinder(QThread):
def askAndUpdate(mw: aqt.AnkiQt, ver: str) -> None: def askAndUpdate(mw: aqt.AnkiQt, ver: str) -> None:
baseStr = tr.qt_misc_anki_updatedanki_has_been_released(val=ver) baseStr = tr.qt_misc_anki_updatedanki_has_been_released(val=ver)
msg = QMessageBox(mw) msg = QMessageBox(mw)
msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) # type: ignore msg.setStandardButtons(QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No) # type: ignore
msg.setIcon(QMessageBox.Information) msg.setIcon(QMessageBox.Icon.Information)
msg.setText(baseStr + tr.qt_misc_would_you_like_to_download_it()) msg.setText(baseStr + tr.qt_misc_would_you_like_to_download_it())
button = QPushButton(tr.qt_misc_ignore_this_update()) button = QPushButton(tr.qt_misc_ignore_this_update())
msg.addButton(button, QMessageBox.RejectRole) msg.addButton(button, QMessageBox.ButtonRole.RejectRole)
msg.setDefaultButton(QMessageBox.Yes) msg.setDefaultButton(QMessageBox.StandardButton.Yes)
ret = msg.exec() ret = msg.exec()
if msg.clickedButton() == button: if msg.clickedButton() == button:
# ignore this update # ignore this update
mw.pm.meta["suppressUpdate"] = ver mw.pm.meta["suppressUpdate"] = ver
elif ret == QMessageBox.Yes: elif ret == QMessageBox.StandardButton.Yes:
openLink(aqt.appWebsite) openLink(aqt.appWebsite)

View file

@ -7,7 +7,7 @@ import re
import subprocess import subprocess
import sys import sys
from functools import wraps from functools import wraps
from typing import TYPE_CHECKING, Any, Literal, Sequence, cast from typing import TYPE_CHECKING, Any, Literal, Sequence
import aqt import aqt
from anki.collection import Collection, HelpPage from anki.collection import Collection, HelpPage
@ -96,16 +96,16 @@ def showInfo(
else: else:
parent_widget = parent parent_widget = parent
if type == "warning": if type == "warning":
icon = QMessageBox.Warning icon = QMessageBox.Icon.Warning
elif type == "critical": elif type == "critical":
icon = QMessageBox.Critical icon = QMessageBox.Icon.Critical
else: else:
icon = QMessageBox.Information icon = QMessageBox.Icon.Information
mb = QMessageBox(parent_widget) # mb = QMessageBox(parent_widget) #
if textFormat == "plain": if textFormat == "plain":
mb.setTextFormat(Qt.PlainText) mb.setTextFormat(Qt.TextFormat.PlainText)
elif textFormat == "rich": elif textFormat == "rich":
mb.setTextFormat(Qt.RichText) mb.setTextFormat(Qt.TextFormat.RichText)
elif textFormat is not None: elif textFormat is not None:
raise Exception("unexpected textFormat type") raise Exception("unexpected textFormat type")
mb.setText(text) mb.setText(text)
@ -119,10 +119,10 @@ def showInfo(
default = b default = b
mb.setDefaultButton(default) mb.setDefaultButton(default)
else: else:
b = mb.addButton(QMessageBox.Ok) b = mb.addButton(QMessageBox.StandardButton.Ok)
b.setDefault(True) b.setDefault(True)
if help: if help:
b = mb.addButton(QMessageBox.Help) b = mb.addButton(QMessageBox.StandardButton.Help)
qconnect(b.clicked, lambda: openHelp(help)) qconnect(b.clicked, lambda: openHelp(help))
b.setAutoDefault(False) b.setAutoDefault(False)
return mb.exec() return mb.exec()
@ -152,7 +152,7 @@ def showText(
# used by the importer # used by the importer
text = QPlainTextEdit() text = QPlainTextEdit()
text.setReadOnly(True) text.setReadOnly(True)
text.setWordWrapMode(QTextOption.NoWrap) text.setWordWrapMode(QTextOption.WrapMode.NoWrap)
text.setPlainText(txt) text.setPlainText(txt)
else: else:
text = QTextBrowser() text = QTextBrowser()
@ -162,7 +162,7 @@ def showText(
else: else:
text.setHtml(txt) text.setHtml(txt)
layout.addWidget(text) layout.addWidget(text)
box = QDialogButtonBox(QDialogButtonBox.Close) box = QDialogButtonBox(QDialogButtonBox.StandardButton.Close)
layout.addWidget(box) layout.addWidget(box)
if copyBtn: if copyBtn:
@ -171,7 +171,7 @@ def showText(
btn = QPushButton(tr.qt_misc_copy_to_clipboard()) btn = QPushButton(tr.qt_misc_copy_to_clipboard())
qconnect(btn.clicked, onCopy) qconnect(btn.clicked, onCopy)
box.addButton(btn, QDialogButtonBox.ActionRole) box.addButton(btn, QDialogButtonBox.ButtonRole.ActionRole)
def onReject() -> None: def onReject() -> None:
if geomKey: if geomKey:
@ -209,20 +209,20 @@ def askUser(
parent = aqt.mw.app.activeWindow() parent = aqt.mw.app.activeWindow()
if not msgfunc: if not msgfunc:
msgfunc = QMessageBox.question msgfunc = QMessageBox.question
sb = QMessageBox.Yes | QMessageBox.No sb = QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
if help: if help:
sb |= QMessageBox.Help sb |= QMessageBox.StandardButton.Help
while 1: while 1:
if defaultno: if defaultno:
default = QMessageBox.No default = QMessageBox.StandardButton.No
else: else:
default = QMessageBox.Yes default = QMessageBox.StandardButton.Yes
r = msgfunc(parent, title, text, cast(QMessageBox.StandardButtons, sb), default) r = msgfunc(parent, title, text, sb, default)
if r == QMessageBox.Help: if r == QMessageBox.StandardButton.Help:
openHelp(help) openHelp(help)
else: else:
break break
return r == QMessageBox.Yes return r == QMessageBox.StandardButton.Yes
class ButtonedDialog(QMessageBox): class ButtonedDialog(QMessageBox):
@ -238,12 +238,12 @@ class ButtonedDialog(QMessageBox):
self._buttons: list[QPushButton] = [] self._buttons: list[QPushButton] = []
self.setWindowTitle(title) self.setWindowTitle(title)
self.help = help self.help = help
self.setIcon(QMessageBox.Warning) self.setIcon(QMessageBox.Icon.Warning)
self.setText(text) self.setText(text)
for b in buttons: for b in buttons:
self._buttons.append(self.addButton(b, QMessageBox.AcceptRole)) self._buttons.append(self.addButton(b, QMessageBox.ButtonRole.AcceptRole))
if help: if help:
self.addButton(tr.actions_help(), QMessageBox.HelpRole) self.addButton(tr.actions_help(), QMessageBox.ButtonRole.HelpRole)
buttons.append(tr.actions_help()) buttons.append(tr.actions_help())
def run(self) -> str: def run(self) -> str:
@ -300,16 +300,21 @@ class GetTextDialog(QDialog):
self.l.setText(default) self.l.setText(default)
self.l.selectAll() self.l.selectAll()
v.addWidget(self.l) v.addWidget(self.l)
buts = QDialogButtonBox.Ok | QDialogButtonBox.Cancel buts = (
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
)
if help: if help:
buts |= QDialogButtonBox.Help buts |= QDialogButtonBox.StandardButton.Help
b = QDialogButtonBox(buts) # type: ignore b = QDialogButtonBox(buts) # type: ignore
v.addWidget(b) v.addWidget(b)
self.setLayout(v) self.setLayout(v)
qconnect(b.button(QDialogButtonBox.Ok).clicked, self.accept) qconnect(b.button(QDialogButtonBox.StandardButton.Ok).clicked, self.accept)
qconnect(b.button(QDialogButtonBox.Cancel).clicked, self.reject) qconnect(b.button(QDialogButtonBox.StandardButton.Cancel).clicked, self.reject)
if help: if help:
qconnect(b.button(QDialogButtonBox.Help).clicked, self.helpRequested) qconnect(
b.button(QDialogButtonBox.StandardButton.Help).clicked,
self.helpRequested,
)
def accept(self) -> None: def accept(self) -> None:
return QDialog.accept(self) return QDialog.accept(self)
@ -337,7 +342,7 @@ def getText(
d = GetTextDialog( d = GetTextDialog(
parent, prompt, help=help, edit=edit, default=default, title=title, **kwargs parent, prompt, help=help, edit=edit, default=default, title=title, **kwargs
) )
d.setWindowModality(Qt.WindowModal) d.setWindowModality(Qt.WindowModality.WindowModal)
if geomKey: if geomKey:
restoreGeom(d, geomKey) restoreGeom(d, geomKey)
ret = d.exec() ret = d.exec()
@ -363,7 +368,7 @@ def chooseList(
parent = aqt.mw.app.activeWindow() parent = aqt.mw.app.activeWindow()
d = QDialog(parent) d = QDialog(parent)
disable_help_button(d) disable_help_button(d)
d.setWindowModality(Qt.WindowModal) d.setWindowModality(Qt.WindowModality.WindowModal)
l = QVBoxLayout() l = QVBoxLayout()
d.setLayout(l) d.setLayout(l)
t = QLabel(prompt) t = QLabel(prompt)
@ -372,7 +377,7 @@ def chooseList(
c.addItems(choices) c.addItems(choices)
c.setCurrentRow(startrow) c.setCurrentRow(startrow)
l.addWidget(c) l.addWidget(c)
bb = QDialogButtonBox(QDialogButtonBox.Ok) bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok)
qconnect(bb.accepted, d.accept) qconnect(bb.accepted, d.accept)
l.addWidget(bb) l.addWidget(bb)
d.exec() d.exec()
@ -393,9 +398,9 @@ def getTag(
def disable_help_button(widget: QWidget) -> None: def disable_help_button(widget: QWidget) -> None:
"Disable the help button in the window titlebar." "Disable the help button in the window titlebar."
flags_int = int(widget.windowFlags()) & ~Qt.WindowContextHelpButtonHint widget.setWindowFlags(
flags = Qt.WindowFlags(flags_int) # type: ignore widget.windowFlags() & ~Qt.WindowType.WindowContextHelpButtonHint
widget.setWindowFlags(flags) )
# File handling # File handling
@ -420,7 +425,11 @@ def getFile(
else: else:
dirkey = None dirkey = None
d = QFileDialog(parent) d = QFileDialog(parent)
mode = QFileDialog.ExistingFiles if multi else QFileDialog.ExistingFile mode = (
QFileDialog.FileMode.ExistingFiles
if multi
else QFileDialog.FileMode.ExistingFile
)
d.setFileMode(mode) d.setFileMode(mode)
if os.path.exists(dir): if os.path.exists(dir):
d.setDirectory(dir) d.setDirectory(dir)
@ -459,7 +468,9 @@ def getSaveFile(
variable. The file dialog will default to open with FNAME.""" variable. The file dialog will default to open with FNAME."""
config_key = f"{dir_description}Directory" config_key = f"{dir_description}Directory"
defaultPath = QStandardPaths.writableLocation(QStandardPaths.DocumentsLocation) defaultPath = QStandardPaths.writableLocation(
QStandardPaths.StandardLocation.DocumentsLocation
)
base = aqt.mw.pm.profile.get(config_key, defaultPath) base = aqt.mw.pm.profile.get(config_key, defaultPath)
path = os.path.join(base, fname) path = os.path.join(base, fname)
file = QFileDialog.getSaveFileName( file = QFileDialog.getSaveFileName(
@ -467,7 +478,7 @@ def getSaveFile(
title, title,
path, path,
f"{key} (*{ext})", f"{key} (*{ext})",
options=QFileDialog.DontConfirmOverwrite, options=QFileDialog.Option.DontConfirmOverwrite,
)[0] )[0]
if file: if file:
# add extension # add extension
@ -485,7 +496,7 @@ def getSaveFile(
def saveGeom(widget: QWidget, key: str) -> None: def saveGeom(widget: QWidget, key: str) -> None:
key += "Geom" key += "Geom"
if isMac and int(widget.windowState()) & Qt.WindowFullScreen: if isMac and (widget.windowState() & Qt.WindowState.WindowFullScreen):
geom = None geom = None
else: else:
geom = widget.saveGeometry() geom = widget.saveGeometry()
@ -646,7 +657,7 @@ def shortcut(key: str) -> str:
def maybeHideClose(bbox: QDialogButtonBox) -> None: def maybeHideClose(bbox: QDialogButtonBox) -> None:
if isMac: if isMac:
b = bbox.button(QDialogButtonBox.Close) b = bbox.button(QDialogButtonBox.StandardButton.Close)
if b: if b:
bbox.removeButton(b) bbox.removeButton(b)
@ -706,13 +717,13 @@ def tooltip(
</table>""", </table>""",
aw, aw,
) )
lab.setFrameStyle(QFrame.Panel) lab.setFrameStyle(QFrame.Shape.Panel)
lab.setLineWidth(2) lab.setLineWidth(2)
lab.setWindowFlags(Qt.ToolTip) lab.setWindowFlags(Qt.WindowType.ToolTip)
if not theme_manager.night_mode: if not theme_manager.night_mode:
p = QPalette() p = QPalette()
p.setColor(QPalette.Window, QColor("#feffc4")) p.setColor(QPalette.ColorRole.Window, QColor("#feffc4"))
p.setColor(QPalette.WindowText, QColor("#000000")) p.setColor(QPalette.ColorRole.WindowText, QColor("#000000"))
lab.setPalette(p) lab.setPalette(p)
lab.move(aw.mapToGlobal(QPoint(0 + x_offset, aw.height() - y_offset))) lab.move(aw.mapToGlobal(QPoint(0 + x_offset, aw.height() - y_offset)))
lab.show() lab.show()
@ -888,7 +899,7 @@ def opengl_vendor() -> str | None:
# Can't use versionFunctions there # Can't use versionFunctions there
return None return None
vp = QOpenGLVersionProfile() # type: ignore vp = QOpenGLVersionProfile() # type: ignore # pylint: disable=undefined-variable
vp.setVersion(2, 0) vp.setVersion(2, 0)
try: try:
@ -969,16 +980,16 @@ class KeyboardModifiersPressed:
def __init__(self) -> None: def __init__(self) -> None:
from aqt import mw from aqt import mw
self._modifiers = int(mw.app.keyboardModifiers()) self._modifiers = mw.app.keyboardModifiers()
@property @property
def shift(self) -> bool: def shift(self) -> bool:
return bool(self._modifiers & Qt.ShiftModifier) return bool(self._modifiers & Qt.KeyboardModifier.ShiftModifier)
@property @property
def control(self) -> bool: def control(self) -> bool:
return bool(self._modifiers & Qt.ControlModifier) return bool(self._modifiers & Qt.KeyboardModifier.ControlModifier)
@property @property
def alt(self) -> bool: def alt(self) -> bool:
return bool(self._modifiers & Qt.AltModifier) return bool(self._modifiers & Qt.KeyboardModifier.AltModifier)

View file

@ -48,7 +48,7 @@ class AnkiWebPage(QWebEnginePage):
qwebchannel = ":/qtwebchannel/qwebchannel.js" qwebchannel = ":/qtwebchannel/qwebchannel.js"
jsfile = QFile(qwebchannel) jsfile = QFile(qwebchannel)
if not jsfile.open(QIODevice.ReadOnly): if not jsfile.open(QIODevice.OpenModeFlag.ReadOnly):
print(f"Error opening '{qwebchannel}': {jsfile.error()}", file=sys.stderr) print(f"Error opening '{qwebchannel}': {jsfile.error()}", file=sys.stderr)
jstext = bytes(cast(bytes, jsfile.readAll())).decode("utf-8") jstext = bytes(cast(bytes, jsfile.readAll())).decode("utf-8")
jsfile.close() jsfile.close()
@ -74,8 +74,8 @@ class AnkiWebPage(QWebEnginePage):
}); });
""" """
) )
script.setWorldId(QWebEngineScript.MainWorld) script.setWorldId(QWebEngineScript.ScriptWorldId.MainWorld)
script.setInjectionPoint(QWebEngineScript.DocumentReady) script.setInjectionPoint(QWebEngineScript.InjectionPoint.DocumentReady)
script.setRunsOnSubFrames(False) script.setRunsOnSubFrames(False)
self.profile().scripts().insert(script) self.profile().scripts().insert(script)
@ -92,11 +92,11 @@ class AnkiWebPage(QWebEnginePage):
srcID = "" srcID = ""
else: else:
srcID = serverbaseurl.sub("", srcID[:80], 1) srcID = serverbaseurl.sub("", srcID[:80], 1)
if level == QWebEnginePage.InfoMessageLevel: if level == QWebEnginePage.JavaScriptConsoleMessageLevel.InfoMessageLevel:
level_str = "info" level_str = "info"
elif level == QWebEnginePage.WarningMessageLevel: elif level == QWebEnginePage.JavaScriptConsoleMessageLevel.WarningMessageLevel:
level_str = "warning" level_str = "warning"
elif level == QWebEnginePage.ErrorMessageLevel: elif level == QWebEnginePage.JavaScriptConsoleMessageLevel.ErrorMessageLevel:
level_str = "error" level_str = "error"
else: else:
level_str = str(level) level_str = str(level)
@ -135,7 +135,9 @@ class AnkiWebPage(QWebEnginePage):
# catch buggy <a href='#' onclick='func()'> links # catch buggy <a href='#' onclick='func()'> links
from aqt import mw from aqt import mw
if url.matches(QUrl(mw.serverURL()), cast(Any, QUrl.RemoveFragment)): if url.matches(
QUrl(mw.serverURL()), cast(Any, QUrl.UrlFormattingOption.RemoveFragment)
):
print("onclick handler needs to return false") print("onclick handler needs to return false")
return False return False
# load all other links in browser # load all other links in browser
@ -240,14 +242,14 @@ class AnkiWebView(QWebEngineView):
self.requiresCol = True self.requiresCol = True
self.setPage(self._page) self.setPage(self._page)
self._page.profile().setHttpCacheType(QWebEngineProfile.NoCache) self._page.profile().setHttpCacheType(QWebEngineProfile.HttpCacheType.NoCache)
self.resetHandlers() self.resetHandlers()
self.allowDrops = False self.allowDrops = False
self._filterSet = False self._filterSet = False
QShortcut( # type: ignore QShortcut( # type: ignore
QKeySequence("Esc"), QKeySequence("Esc"),
self, self,
context=Qt.WidgetWithChildrenShortcut, context=Qt.ShortcutContext.WidgetWithChildrenShortcut,
activated=self.onEsc, activated=self.onEsc,
) )
@ -258,8 +260,11 @@ class AnkiWebView(QWebEngineView):
# disable pinch to zoom gesture # disable pinch to zoom gesture
if isinstance(evt, QNativeGestureEvent): if isinstance(evt, QNativeGestureEvent):
return True return True
elif isinstance(evt, QMouseEvent) and evt.type() == QEvent.MouseButtonRelease: elif (
if evt.button() == Qt.MidButton and isLin: isinstance(evt, QMouseEvent)
and evt.type() == QEvent.Type.MouseButtonRelease
):
if evt.button() == Qt.MouseButton.MiddleButton and isLin:
self.onMiddleClickPaste() self.onMiddleClickPaste()
return True return True
return False return False
@ -286,19 +291,19 @@ class AnkiWebView(QWebEngineView):
w = w.parent() w = w.parent()
def onCopy(self) -> None: def onCopy(self) -> None:
self.triggerPageAction(QWebEnginePage.Copy) self.triggerPageAction(QWebEnginePage.WebAction.Copy)
def onCut(self) -> None: def onCut(self) -> None:
self.triggerPageAction(QWebEnginePage.Cut) self.triggerPageAction(QWebEnginePage.WebAction.Cut)
def onPaste(self) -> None: def onPaste(self) -> None:
self.triggerPageAction(QWebEnginePage.Paste) self.triggerPageAction(QWebEnginePage.WebAction.Paste)
def onMiddleClickPaste(self) -> None: def onMiddleClickPaste(self) -> None:
self.triggerPageAction(QWebEnginePage.Paste) self.triggerPageAction(QWebEnginePage.WebAction.Paste)
def onSelectAll(self) -> None: def onSelectAll(self) -> None:
self.triggerPageAction(QWebEnginePage.SelectAll) self.triggerPageAction(QWebEnginePage.WebAction.SelectAll)
def contextMenuEvent(self, evt: QContextMenuEvent) -> None: def contextMenuEvent(self, evt: QContextMenuEvent) -> None:
m = QMenu(self) m = QMenu(self)
@ -386,11 +391,11 @@ class AnkiWebView(QWebEngineView):
# standard palette does not return correct window color on macOS # standard palette does not return correct window color on macOS
return QColor("#ececec") return QColor("#ececec")
else: else:
return theme_manager.default_palette.color(QPalette.Window) return theme_manager.default_palette.color(QPalette.ColorRole.Window)
def standard_css(self) -> str: def standard_css(self) -> str:
palette = theme_manager.default_palette palette = theme_manager.default_palette
color_hl = palette.color(QPalette.Highlight).name() color_hl = palette.color(QPalette.ColorRole.Highlight).name()
if isWin: if isWin:
# T: include a font for your language on Windows, eg: "Segoe UI", "MS Mincho" # T: include a font for your language on Windows, eg: "Segoe UI", "MS Mincho"
@ -406,8 +411,8 @@ button { -webkit-appearance: none; background: #fff; border: 1px solid #ccc;
border-radius:5px; font-family: Helvetica }""" border-radius:5px; font-family: Helvetica }"""
else: else:
family = self.font().family() family = self.font().family()
color_hl_txt = palette.color(QPalette.HighlightedText).name() color_hl_txt = palette.color(QPalette.ColorRole.HighlightedText).name()
color_btn = palette.color(QPalette.Button).name() color_btn = palette.color(QPalette.ColorRole.Button).name()
font = f'font-size:14px;font-family:"{family}";' font = f'font-size:14px;font-family:"{family}";'
button_style = """ button_style = """
/* Buttons */ /* Buttons */

View file

@ -36,7 +36,7 @@ if subprocess.run(
os.path.abspath("pip/stubs/extendsitepkgs"), os.path.abspath("pip/stubs/extendsitepkgs"),
], ],
env={ env={
"MYPYPATH": "bazel-bin/qt/dmypy.runfiles/pyqt5", "MYPYPATH": "bazel-bin/qt/dmypy.runfiles/pyqt6",
"EXTRA_SITE_PACKAGES": os.path.abspath(os.getenv("EXTRA_SITE_PACKAGES")), "EXTRA_SITE_PACKAGES": os.path.abspath(os.getenv("EXTRA_SITE_PACKAGES")),
}, },
cwd=workspace, cwd=workspace,

View file

@ -54,6 +54,7 @@ ignore_missing_imports = True
ignore_missing_imports = True ignore_missing_imports = True
[mypy-PyQt5.*] [mypy-PyQt5.*]
ignore_errors = True ignore_errors = True
ignore_missing_imports = True
[mypy-win32com.client] [mypy-win32com.client]
ignore_missing_imports = True ignore_missing_imports = True
[mypy-darkdetect] [mypy-darkdetect]