diff --git a/qt/.pylintrc b/qt/.pylintrc index 510c08da4..6107eeed3 100644 --- a/qt/.pylintrc +++ b/qt/.pylintrc @@ -1,6 +1,6 @@ [MASTER] persistent = no -extension-pkg-whitelist=PyQt5,PyQt6 +extension-pkg-whitelist=PyQt6 ignore = forms,hooks_gen.py [TYPECHECK] diff --git a/qt/BUILD.bazel b/qt/BUILD.bazel index a2e4bfd65..93d5473b3 100644 --- a/qt/BUILD.bazel +++ b/qt/BUILD.bazel @@ -45,21 +45,21 @@ py_test( args = [ "aqt", "$(location mypy.ini)", - "$(location @pyqt5//:__init__.py)", + "$(location @pyqt6//:__init__.py)", "$(location //pip/stubs:extendsitepkgs)", ], data = [ "mypy.ini", "//pip/stubs", "//pip/stubs:extendsitepkgs", - "@pyqt5//:__init__.py", + "@pyqt6//:__init__.py", ], env = {"EXTRA_SITE_PACKAGES": "$(location //pip/stubs)"}, main = "tests/run_mypy.py", deps = [ "//pylib/anki", "//qt/aqt:aqt_without_data", - "@pyqt5//:pkg", + "@pyqt6//:pkg", requirement("mypy"), ], ) diff --git a/qt/aqt/BUILD.bazel b/qt/aqt/BUILD.bazel index e4bac550a..ad816a68b 100644 --- a/qt/aqt/BUILD.bazel +++ b/qt/aqt/BUILD.bazel @@ -50,7 +50,7 @@ aqt_deps = [ requirement("waitress"), requirement("send2trash"), requirement("jsonschema"), - "@pyqt5//:pkg", + "@pyqt6//:pkg", ] + select({ "@bazel_tools//src/conditions:host_windows": [ requirement("psutil"), diff --git a/qt/aqt/__init__.py b/qt/aqt/__init__.py index f910bbc1f..ea2742d7d 100644 --- a/qt/aqt/__init__.py +++ b/qt/aqt/__init__.py @@ -99,8 +99,10 @@ class DialogManager: def open(self, name: str, *args: Any, **kwargs: Any) -> Any: (creator, instance) = self._dialogs[name] if instance: - if instance.windowState() & Qt.WindowMinimized: - instance.setWindowState(instance.windowState() & ~Qt.WindowMinimized) + if instance.windowState() & Qt.WindowState.WindowMinimized: + instance.setWindowState( + instance.windowState() & ~Qt.WindowState.WindowMinimized + ) instance.activateWindow() instance.raise_() if hasattr(instance, "reopen"): @@ -224,9 +226,9 @@ def setupLangAndBackend( # switch direction for RTL languages if anki.lang.is_rtl(lang): - app.setLayoutDirection(Qt.RightToLeft) + app.setLayoutDirection(Qt.LayoutDirection.RightToLeft) else: - app.setLayoutDirection(Qt.LeftToRight) + app.setLayoutDirection(Qt.LayoutDirection.LeftToRight) # load qt translations _qtrans = QTranslator() @@ -238,7 +240,10 @@ def setupLangAndBackend( os.path.join(aqt_data_folder(), "..", "qt_translations") ) 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("-", "_") if _qtrans.load(f"qtbase_{qt_lang}", qt_dir): app.installTranslator(_qtrans) @@ -285,7 +290,7 @@ class AnkiApp(QApplication): def sendMsg(self, txt: str) -> bool: sock = QLocalSocket(self) - sock.connectToServer(self.KEY, QIODevice.WriteOnly) + sock.connectToServer(self.KEY, QIODevice.OpenModeFlag.WriteOnly) if not sock.waitForConnected(self.TMOUT): # first instance or previous instance dead return False @@ -315,7 +320,7 @@ class AnkiApp(QApplication): ################################################## 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 return True return QApplication.event(self, evt) @@ -360,17 +365,17 @@ def setupGL(pm: aqt.profiles.ProfileManager) -> None: # catch opengl errors def msgHandler(category: Any, ctx: Any, msg: Any) -> None: - if category == QtDebugMsg: + if category == QtMsgType.QtDebugMsg: category = "debug" - elif category == QtInfoMsg: + elif category == QtMsgType.QtInfoMsg: category = "info" - elif category == QtWarningMsg: + elif category == QtMsgType.QtWarningMsg: category = "warning" - elif category == QtCriticalMsg: + elif category == QtMsgType.QtCriticalMsg: category = "critical" - elif category == QtDebugMsg: + elif category == QtMsgType.QtDebugMsg: category = "debug" - elif category == QtFatalMsg: + elif category == QtMsgType.QtFatalMsg: category = "fatal" else: category = "unknown" @@ -405,7 +410,7 @@ def setupGL(pm: aqt.profiles.ProfileManager) -> None: if isWin: os.environ["QT_OPENGL"] = driver.value elif isMac: - QCoreApplication.setAttribute(Qt.AA_UseSoftwareOpenGL) + QCoreApplication.setAttribute(Qt.ApplicationAttribute.AA_UseSoftwareOpenGL) elif isLin: 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()) # opt in to full hidpi support? - if not os.environ.get("ANKI_NOHIGHDPI"): - QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling) - QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps) + if not os.environ.get("ANKI_NOHIGHDPI") and qtmajor == 5: + QCoreApplication.setAttribute(Qt.ApplicationAttribute.AA_EnableHighDpiScaling) # type: ignore + QCoreApplication.setAttribute(Qt.ApplicationAttribute.AA_UseHighDpiPixmaps) # type: ignore os.environ["QT_ENABLE_HIGHDPI_SCALING"] = "1" os.environ["QT_SCALE_FACTOR_ROUNDING_POLICY"] = "PassThrough" # Opt into software rendering. Useful for buggy systems. if os.environ.get("ANKI_SOFTWAREOPENGL"): - QCoreApplication.setAttribute(Qt.AA_UseSoftwareOpenGL) + QCoreApplication.setAttribute(Qt.ApplicationAttribute.AA_UseSoftwareOpenGL) if ( 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 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 - if isWin and qtminor >= 10: - QApplication.setAttribute(Qt.AA_DisableWindowContextHelpButton) + if isWin and qtmajor == 5 and qtminor >= 10: + QApplication.setAttribute( + QApplication.Attribute.AA_DisableWindowContextHelpButton # type: ignore + ) # proxy configured? 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: print("webview proxy use disabled") proxy = QNetworkProxy() - proxy.setType(QNetworkProxy.NoProxy) + proxy.setType(QNetworkProxy.ProxyType.NoProxy) QNetworkProxy.setApplicationProxy(proxy) # we must have a usable temp dir diff --git a/qt/aqt/about.py b/qt/aqt/about.py index 357d346ec..3f5d47164 100644 --- a/qt/aqt/about.py +++ b/qt/aqt/about.py @@ -88,8 +88,8 @@ def show(mw: aqt.AnkiQt) -> QDialog: btn = QPushButton(tr.about_copy_debug_info()) qconnect(btn.clicked, onCopy) - abt.buttonBox.addButton(btn, QDialogButtonBox.ActionRole) - abt.buttonBox.button(QDialogButtonBox.Ok).setFocus() + abt.buttonBox.addButton(btn, QDialogButtonBox.ButtonRole.ActionRole) + abt.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setFocus() # WebView contents ###################################################################### diff --git a/qt/aqt/addcards.py b/qt/aqt/addcards.py index f5280c233..7d42ba133 100644 --- a/qt/aqt/addcards.py +++ b/qt/aqt/addcards.py @@ -35,7 +35,7 @@ from aqt.utils import ( class AddCards(QDialog): 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) self.mw = mw self.col = mw.col @@ -85,7 +85,7 @@ class AddCards(QDialog): def setupButtons(self) -> None: bb = self.form.buttonBox - ar = QDialogButtonBox.ActionRole + ar = QDialogButtonBox.ButtonRole.ActionRole # add self.addButton = bb.addButton(tr.actions_add(), ar) qconnect(self.addButton.clicked, self.add_current_note) @@ -97,11 +97,11 @@ class AddCards(QDialog): # close self.closeButton = QPushButton(tr.actions_close()) self.closeButton.setAutoDefault(False) - bb.addButton(self.closeButton, QDialogButtonBox.RejectRole) + bb.addButton(self.closeButton, QDialogButtonBox.ButtonRole.RejectRole) # help self.helpButton = QPushButton(tr.actions_help(), clicked=self.helpRequested) # type: ignore self.helpButton.setAutoDefault(False) - bb.addButton(self.helpButton, QDialogButtonBox.HelpRole) + bb.addButton(self.helpButton, QDialogButtonBox.ButtonRole.HelpRole) # history b = bb.addButton(f"{tr.adding_history()} {downArrow()}", ar) if isMac: @@ -266,7 +266,10 @@ class AddCards(QDialog): def keyPressEvent(self, evt: QKeyEvent) -> None: "Show answer on RET or register answer." - if evt.key() in (Qt.Key_Enter, Qt.Key_Return) and self.editor.tags.hasFocus(): + if ( + evt.key() in (Qt.Key.Key_Enter, Qt.Key.Key_Return) + and self.editor.tags.hasFocus() + ): evt.accept() return return QDialog.keyPressEvent(self, evt) diff --git a/qt/aqt/addons.py b/qt/aqt/addons.py index 5a94e048a..c8c69b6de 100644 --- a/qt/aqt/addons.py +++ b/qt/aqt/addons.py @@ -804,7 +804,7 @@ class AddonsDialog(QDialog): name = self.name_for_addon_list(addon) item = QListWidgetItem(name, addonList) if self.should_grey(addon): - item.setForeground(Qt.gray) + item.setForeground(Qt.GlobalColor.gray) if addon.dir_name in selected: item.setSelected(True) @@ -947,7 +947,7 @@ class GetAddons(QDialog): self.form = aqt.forms.getaddons.Ui_Dialog() self.form.setupUi(self) b = self.form.buttonBox.addButton( - tr.addons_browse_addons(), QDialogButtonBox.ActionRole + tr.addons_browse_addons(), QDialogButtonBox.ButtonRole.ActionRole ) qconnect(b.clicked, self.onBrowse) disable_help_button(self) @@ -1183,7 +1183,7 @@ class ChooseAddonsToUpdateList(QListWidget): ) self.ignore_check_evt = False self.setup() - self.setContextMenuPolicy(Qt.CustomContextMenu) + self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) qconnect(self.itemClicked, self.on_click) qconnect(self.itemChanged, self.on_check) qconnect(self.itemDoubleClicked, self.on_double_click) @@ -1191,7 +1191,9 @@ class ChooseAddonsToUpdateList(QListWidget): def setup(self) -> None: 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 for update_info in self.updated_addons: addon_id = update_info.id @@ -1204,22 +1206,22 @@ class ChooseAddonsToUpdateList(QListWidget): addon_label = f"{update_time:%Y-%m-%d} {addon_name}" item = QListWidgetItem(addon_label, self) # 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: - item.setCheckState(Qt.Checked) + item.setCheckState(Qt.CheckState.Checked) else: - item.setCheckState(Qt.Unchecked) + item.setCheckState(Qt.CheckState.Unchecked) item.setData(self.ADDON_ID_ROLE, addon_id) self.refresh_header_check_state() def bool_to_check(self, check_bool: bool) -> Qt.CheckState: if check_bool: - return Qt.Checked + return Qt.CheckState.Checked else: - return Qt.Unchecked + return Qt.CheckState.Unchecked def checked(self, item: QListWidgetItem) -> bool: - return item.checkState() == Qt.Checked + return item.checkState() == Qt.CheckState.Checked def on_click(self, item: QListWidgetItem) -> None: if item == self.header_item: @@ -1262,9 +1264,9 @@ class ChooseAddonsToUpdateList(QListWidget): for i in range(1, self.count()): item = self.item(i) if not self.checked(item): - self.check_item(self.header_item, Qt.Unchecked) + self.check_item(self.header_item, Qt.CheckState.Unchecked) 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]: addon_ids = [] @@ -1290,7 +1292,7 @@ class ChooseAddonsToUpdateDialog(QDialog): ) -> None: QDialog.__init__(self, parent) self.setWindowTitle(tr.addons_choose_update_window_title()) - self.setWindowModality(Qt.WindowModal) + self.setWindowModality(Qt.WindowModality.WindowModal) self.mgr = mgr self.updated_addons = updated_addons self.setup() @@ -1306,9 +1308,14 @@ class ChooseAddonsToUpdateDialog(QDialog): layout.addWidget(addons_list_widget) self.addons_list_widget = addons_list_widget - button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) # type: ignore - qconnect(button_box.button(QDialogButtonBox.Ok).clicked, self.accept) - qconnect(button_box.button(QDialogButtonBox.Cancel).clicked, self.reject) + button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) # type: ignore + qconnect( + button_box.button(QDialogButtonBox.StandardButton.Ok).clicked, self.accept + ) + qconnect( + button_box.button(QDialogButtonBox.StandardButton.Cancel).clicked, + self.reject, + ) layout.addWidget(button_box) self.setLayout(layout) @@ -1317,7 +1324,7 @@ class ChooseAddonsToUpdateDialog(QDialog): ret = self.exec() saveGeom(self, "addonsChooseUpdate") 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() else: return [] @@ -1475,7 +1482,9 @@ class ConfigEditor(QDialog): self.mgr = dlg.mgr self.form = aqt.forms.addonconf.Ui_Dialog() self.form.setupUi(self) - restore = self.form.buttonBox.button(QDialogButtonBox.RestoreDefaults) + restore = self.form.buttonBox.button( + QDialogButtonBox.StandardButton.RestoreDefaults + ) qconnect(restore.clicked, self.onRestoreDefaults) self.setupFonts() self.updateHelp() @@ -1498,7 +1507,7 @@ class ConfigEditor(QDialog): tooltip(tr.addons_restored_defaults(), parent=self) def setupFonts(self) -> None: - font_mono = QFontDatabase.systemFont(QFontDatabase.FixedFont) + font_mono = QFontDatabase.systemFont(QFontDatabase.SystemFont.FixedFont) font_mono.setPointSize(font_mono.pointSize() + 1) self.form.editor.setFont(font_mono) @@ -1600,9 +1609,12 @@ def installAddonPackages( parent=parent, title=tr.addons_install_anki_addon(), type="warning", - customBtns=[QMessageBox.No, QMessageBox.Yes], + customBtns=[ + QMessageBox.StandardButton.No, + QMessageBox.StandardButton.Yes, + ], ) - == QMessageBox.Yes + == QMessageBox.StandardButton.Yes ): return False diff --git a/qt/aqt/browser/browser.py b/qt/aqt/browser/browser.py index 34a6133fe..1c90beeaf 100644 --- a/qt/aqt/browser/browser.py +++ b/qt/aqt/browser/browser.py @@ -104,7 +104,7 @@ class Browser(QMainWindow): 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.col = self.mw.col self.lastFilter = "" @@ -255,7 +255,7 @@ class Browser(QMainWindow): onsuccess() def keyPressEvent(self, evt: QKeyEvent) -> None: - if evt.key() == Qt.Key_Escape: + if evt.key() == Qt.Key.Key_Escape: self.close() else: super().keyPressEvent(evt) @@ -490,9 +490,9 @@ class Browser(QMainWindow): def setupSidebar(self) -> None: dw = self.sidebarDockWidget = QDockWidget(tr.browsing_sidebar(), self) - dw.setFeatures(QDockWidget.NoDockWidgetFeatures) + dw.setFeatures(QDockWidget.DockWidgetFeature.NoDockWidgetFeatures) dw.setObjectName("Sidebar") - dw.setAllowedAreas(Qt.LeftDockWidgetArea) + dw.setAllowedAreas(Qt.DockWidgetArea.LeftDockWidgetArea) self.sidebar = SidebarTreeView(self) self.sidebarTree = self.sidebar # legacy alias @@ -513,7 +513,7 @@ class Browser(QMainWindow): self.sidebarDockWidget.setFloating(False) 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 # UI is more responsive diff --git a/qt/aqt/browser/card_info.py b/qt/aqt/browser/card_info.py index 046870362..b059bfaa5 100644 --- a/qt/aqt/browser/card_info.py +++ b/qt/aqt/browser/card_info.py @@ -28,7 +28,7 @@ class CardInfoDialog(QDialog): self.show() 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) disable_help_button(self) restoreGeom(self, self.GEOMETRY_KEY) @@ -40,7 +40,7 @@ class CardInfoDialog(QDialog): layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.web) - buttons = QDialogButtonBox(QDialogButtonBox.Close) + buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Close) buttons.setContentsMargins(10, 0, 10, 10) layout.addWidget(buttons) qconnect(buttons.rejected, self.reject) diff --git a/qt/aqt/browser/find_and_replace.py b/qt/aqt/browser/find_and_replace.py index 60b2f3d77..39add80e6 100644 --- a/qt/aqt/browser/find_and_replace.py +++ b/qt/aqt/browser/find_and_replace.py @@ -73,16 +73,18 @@ class FindAndReplaceDialog(QDialog): disable_help_button(self) self.form = aqt.forms.findreplace.Ui_Dialog() self.form.setupUi(self) - self.setWindowModality(Qt.WindowModal) + self.setWindowModality(Qt.WindowModality.WindowModal) self._find_history = restore_combo_history( 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.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: # no selected notes to affect diff --git a/qt/aqt/browser/find_duplicates.py b/qt/aqt/browser/find_duplicates.py index bd5c3237d..4af17cfe2 100644 --- a/qt/aqt/browser/find_duplicates.py +++ b/qt/aqt/browser/find_duplicates.py @@ -71,7 +71,7 @@ class FindDuplicatesDialog(QDialog): ).run_in_background() search = form.buttonBox.addButton( - tr.actions_search(), QDialogButtonBox.ActionRole + tr.actions_search(), QDialogButtonBox.ButtonRole.ActionRole ) qconnect(search.clicked, on_click) self.show() @@ -80,7 +80,7 @@ class FindDuplicatesDialog(QDialog): self._dupes = dupes if not self._dupesButton: 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) text = "" diff --git a/qt/aqt/browser/previewer.py b/qt/aqt/browser/previewer.py index 774354070..190d65ecb 100644 --- a/qt/aqt/browser/previewer.py +++ b/qt/aqt/browser/previewer.py @@ -46,14 +46,14 @@ class Previewer(QDialog): def __init__( self, parent: QWidget, mw: AnkiQt, on_close: Callable[[], None] ) -> None: - super().__init__(None, Qt.Window) + super().__init__(None, Qt.WindowType.Window) mw.garbage_collect_on_dialog_finish(self) self._open = True self._parent = parent self._close_callback = on_close self.mw = mw 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) self.setWindowIcon(icon) @@ -86,7 +86,7 @@ class Previewer(QDialog): self.bbox = QDialogButtonBox() self._replay = self.bbox.addButton( - tr.actions_replay_audio(), QDialogButtonBox.ActionRole + tr.actions_replay_audio(), QDialogButtonBox.ButtonRole.ActionRole ) self._replay.setAutoDefault(False) 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.setShortcut(QKeySequence("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( Config.Bool.PREVIEW_BOTH_SIDES ) @@ -266,12 +266,12 @@ class MultiCardPreviewer(Previewer): def _create_gui(self) -> None: super()._create_gui() - self._prev = self.bbox.addButton("<", QDialogButtonBox.ActionRole) + self._prev = self.bbox.addButton("<", QDialogButtonBox.ButtonRole.ActionRole) self._prev.setAutoDefault(False) self._prev.setShortcut(QKeySequence("Left")) 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.setShortcut(QKeySequence("Right")) self._next.setToolTip(tr.qt_misc_shortcut_key_right_arrow_or_enter()) diff --git a/qt/aqt/browser/sidebar/model.py b/qt/aqt/browser/sidebar/model.py index 6376f176f..e9b3062d3 100644 --- a/qt/aqt/browser/sidebar/model.py +++ b/qt/aqt/browser/sidebar/model.py @@ -76,35 +76,48 @@ class SidebarModel(QAbstractItemModel): 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(): 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() item: SidebarItem = index.internalPointer() - if role in (Qt.DisplayRole, Qt.EditRole): + if role in (Qt.ItemDataRole.DisplayRole, Qt.ItemDataRole.EditRole): return QVariant(item.name) - if role == Qt.ToolTipRole: + if role == Qt.ItemDataRole.ToolTipRole: return QVariant(item.tooltip) 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) - def supportedDropActions(self) -> Qt.DropActions: - return cast(Qt.DropActions, Qt.MoveAction) + def supportedDropActions(self) -> Qt.DropAction: + 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(): - return cast(Qt.ItemFlags, Qt.ItemIsEnabled) - flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled + return cast(Qt.ItemFlag, Qt.ItemFlag.ItemIsEnabled) + flags = ( + Qt.ItemFlag.ItemIsEnabled + | Qt.ItemFlag.ItemIsSelectable + | Qt.ItemFlag.ItemIsDragEnabled + ) item: SidebarItem = index.internalPointer() if item.item_type in self.sidebar.valid_drop_types: - flags |= Qt.ItemIsDropEnabled + flags |= Qt.ItemFlag.ItemIsDropEnabled if item.item_type.is_editable(): - flags |= Qt.ItemIsEditable + flags |= Qt.ItemFlag.ItemIsEditable - return cast(Qt.ItemFlags, flags) + return flags diff --git a/qt/aqt/browser/sidebar/searchbar.py b/qt/aqt/browser/sidebar/searchbar.py index b06ad7fcb..ae08f22fb 100644 --- a/qt/aqt/browser/sidebar/searchbar.py +++ b/qt/aqt/browser/sidebar/searchbar.py @@ -43,9 +43,9 @@ class SidebarSearchBar(QLineEdit): self.sidebar.search_for(self.text()) 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() - elif evt.key() in (Qt.Key_Enter, Qt.Key_Return): + elif evt.key() in (Qt.Key.Key_Enter, Qt.Key.Key_Return): self.onSearch() else: QLineEdit.keyPressEvent(self, evt) diff --git a/qt/aqt/browser/sidebar/toolbar.py b/qt/aqt/browser/sidebar/toolbar.py index 61a0b0b5e..3f544682d 100644 --- a/qt/aqt/browser/sidebar/toolbar.py +++ b/qt/aqt/browser/sidebar/toolbar.py @@ -29,7 +29,7 @@ class SidebarToolbar(QToolBar): qconnect(self._action_group.triggered, self._on_action_group_triggered) self._setup_tools() self.setIconSize(QSize(16, 16)) - self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + self.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) self.setStyle(QStyleFactory.create("fusion")) def _setup_tools(self) -> None: diff --git a/qt/aqt/browser/sidebar/tree.py b/qt/aqt/browser/sidebar/tree.py index c48e45491..02be98c58 100644 --- a/qt/aqt/browser/sidebar/tree.py +++ b/qt/aqt/browser/sidebar/tree.py @@ -79,14 +79,14 @@ class SidebarTreeView(QTreeView): self.valid_drop_types: tuple[SidebarItemType, ...] = () self._refresh_needed = False - self.setContextMenuPolicy(Qt.CustomContextMenu) + self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) self.customContextMenuRequested.connect(self.onContextMenu) # type: ignore self.setUniformRowHeights(True) self.setHeaderHidden(True) self.setIndentation(15) self.setAutoExpandDelay(600) self.setDragDropOverwriteMode(False) - self.setEditTriggers(QAbstractItemView.EditKeyPressed) + self.setEditTriggers(QAbstractItemView.EditTrigger.EditKeyPressed) qconnect(self.expanded, self._on_expansion) qconnect(self.collapsed, self._on_collapse) @@ -122,12 +122,12 @@ class SidebarTreeView(QTreeView): def tool(self, tool: SidebarTool) -> None: self._tool = tool if tool == SidebarTool.SEARCH: - selection_mode = QAbstractItemView.SingleSelection - drag_drop_mode = QAbstractItemView.NoDragDrop + selection_mode = QAbstractItemView.SelectionMode.SingleSelection + drag_drop_mode = QAbstractItemView.DragDropMode.NoDragDrop double_click_expands = False else: - selection_mode = QAbstractItemView.ExtendedSelection - drag_drop_mode = QAbstractItemView.InternalMove + selection_mode = QAbstractItemView.SelectionMode.ExtendedSelection + drag_drop_mode = QAbstractItemView.DragDropMode.InternalMove double_click_expands = True self.setSelectionMode(selection_mode) self.setDragDropMode(drag_drop_mode) @@ -191,9 +191,9 @@ class SidebarTreeView(QTreeView): if current := self.find_item(current.has_same_id): index = self.model().index_for_item(current) self.selectionModel().setCurrentIndex( - index, QItemSelectionModel.SelectCurrent + index, QItemSelectionModel.SelectionFlag.SelectCurrent ) - self.scrollTo(index, QAbstractItemView.PositionAtCenter) + self.scrollTo(index, QAbstractItemView.ScrollHint.PositionAtCenter) def find_item( self, @@ -247,9 +247,12 @@ class SidebarTreeView(QTreeView): self.setExpanded(idx, True) if item.is_highlighted() and scroll_to_first_match: 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 expand_node(parent or QModelIndex()) @@ -301,22 +304,29 @@ class SidebarTreeView(QTreeView): def dropEvent(self, event: QDropEvent) -> None: 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): event.acceptProposedAction() def mouseReleaseEvent(self, event: QMouseEvent) -> None: 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()): self._on_search(index) def keyPressEvent(self, event: QKeyEvent) -> None: 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): self._on_search(index) - elif event.key() == Qt.Key_Delete: + elif event.key() == Qt.Key.Key_Delete: self._on_delete_key(index) else: super().keyPressEvent(event) diff --git a/qt/aqt/browser/table/model.py b/qt/aqt/browser/table/model.py index f2ab6270b..e997bf230 100644 --- a/qt/aqt/browser/table/model.py +++ b/qt/aqt/browser/table/model.py @@ -3,7 +3,7 @@ from __future__ import annotations import time -from typing import Any, Callable, Sequence, cast +from typing import Any, Callable, Sequence import aqt from anki.cards import Card, CardId @@ -307,7 +307,7 @@ class DataModel(QAbstractTableModel): def data(self, index: QModelIndex = QModelIndex(), role: int = 0) -> Any: if not index.isValid(): return QVariant() - if role == Qt.FontRole: + if role == Qt.ItemDataRole.FontRole: if not self.column_at(index).uses_cell_font: return QVariant() qfont = QFont() @@ -315,30 +315,33 @@ class DataModel(QAbstractTableModel): qfont.setFamily(row.font_name) qfont.setPixelSize(row.font_size) return qfont - elif role == Qt.TextAlignmentRole: - align: Qt.AlignmentFlag | int = Qt.AlignVCenter + elif role == Qt.ItemDataRole.TextAlignmentRole: + align: Qt.AlignmentFlag | int = Qt.AlignmentFlag.AlignVCenter if self.column_at(index).alignment == Columns.ALIGNMENT_CENTER: - align |= Qt.AlignHCenter + align |= Qt.AlignmentFlag.AlignHCenter return align - elif role == Qt.DisplayRole: + elif role == Qt.ItemDataRole.DisplayRole: 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 QVariant() def headerData( self, section: int, orientation: Qt.Orientation, role: int = 0 ) -> 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 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 if row := self.get_cached_row(index): if row.is_deleted: - return Qt.ItemFlags(Qt.NoItemFlags) - return cast(Qt.ItemFlags, Qt.ItemIsEnabled | Qt.ItemIsSelectable) + return Qt.ItemFlag(Qt.ItemFlag.NoItemFlags) + return Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable def addon_column_fillin(key: str) -> Column: diff --git a/qt/aqt/browser/table/table.py b/qt/aqt/browser/table/table.py index f1eef337a..d08858b46 100644 --- a/qt/aqt/browser/table/table.py +++ b/qt/aqt/browser/table/table.py @@ -2,7 +2,7 @@ # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html from __future__ import annotations -from typing import Any, Callable, Sequence, cast +from typing import Any, Callable, Sequence import aqt import aqt.forms @@ -127,10 +127,8 @@ class Table: self.select_all() self._view.selectionModel().select( selection, - cast( - QItemSelectionModel.SelectionFlags, - QItemSelectionModel.Deselect | QItemSelectionModel.Rows, - ), + QItemSelectionModel.SelectionFlag.Deselect + | QItemSelectionModel.SelectionFlag.Rows, ) def select_single_card(self, card_id: CardId) -> None: @@ -202,10 +200,10 @@ class Table: # Move cursor def to_previous_row(self) -> None: - self._move_current(QAbstractItemView.MoveUp) + self._move_current(QAbstractItemView.CursorAction.MoveUp) def to_next_row(self) -> None: - self._move_current(QAbstractItemView.MoveDown) + self._move_current(QAbstractItemView.CursorAction.MoveDown) def to_first_row(self) -> None: self._move_current_to_row(0) @@ -248,7 +246,8 @@ class Table: def clear_current(self) -> None: self._view.selectionModel().setCurrentIndex( - QModelIndex(), QItemSelectionModel.NoUpdate + QModelIndex(), + QItemSelectionModel.SelectionFlag.NoUpdate, ) # Private methods @@ -268,7 +267,10 @@ class Table: index = self._model.index( 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: """Remove selection and focus without emitting signals. @@ -286,7 +288,9 @@ class Table: self._model.index(row, 0), 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: hh = self._view.horizontalHeader() @@ -295,9 +299,9 @@ class Table: hh.setSortIndicatorShown(False) return if self._state.sort_backwards: - order = Qt.DescendingOrder + order = Qt.SortOrder.DescendingOrder else: - order = Qt.AscendingOrder + order = Qt.SortOrder.AscendingOrder hh.blockSignals(True) hh.setSortIndicator(index, order) hh.blockSignals(False) @@ -305,9 +309,10 @@ class Table: def _set_column_sizes(self) -> None: hh = self._view.horizontalHeader() - hh.setSectionResizeMode(QHeaderView.Interactive) + hh.setSectionResizeMode(QHeaderView.ResizeMode.Interactive) 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 hh.setCascadingSectionResizes(False) @@ -334,7 +339,7 @@ class Table: ) qconnect(self._view.selectionModel().currentChanged, self._on_current_changed) self._view.setWordWrap(False) - self._view.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel) + self._view.setHorizontalScrollMode(QAbstractItemView.ScrollMode.ScrollPerPixel) self._view.horizontalScrollBar().setSingleStep(10) self._update_font() if not theme_manager.night_mode: @@ -346,7 +351,7 @@ class Table: self._view.setStyleSheet( 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) def _update_font(self) -> None: @@ -369,7 +374,7 @@ class Table: hh.setHighlightSections(False) hh.setMinimumSectionSize(50) hh.setSectionsMovable(True) - hh.setContextMenuPolicy(Qt.CustomContextMenu) + hh.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) self._restore_header() qconnect(hh.customContextMenuRequested, self._on_header_context) 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() if not visible or scroll_even_if_visible: 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) def _scroll_to_column(self, column: int) -> None: @@ -583,26 +590,26 @@ class Table: if not visible: vertical = self._view.verticalScrollBar().value() self._view.scrollTo( - self._model.index(0, column), self._view.PositionAtCenter + self._model.index(0, column), + QAbstractItemView.ScrollHint.PositionAtCenter, ) 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(): return if index is None: index = self._view.moveCursor( - cast(QAbstractItemView.CursorAction, direction), + direction, self.browser.mw.app.keyboardModifiers(), ) self._view.selectionModel().setCurrentIndex( index, - cast( - QItemSelectionModel.SelectionFlag, - QItemSelectionModel.Clear - | QItemSelectionModel.Select - | QItemSelectionModel.Rows, - ), + QItemSelectionModel.SelectionFlag.Clear + | QItemSelectionModel.SelectionFlag.Select + | QItemSelectionModel.SelectionFlag.Rows, ) def _move_current_to_row(self, row: int) -> None: @@ -614,10 +621,8 @@ class Table: selection = QItemSelection(new, old) self._view.selectionModel().select( selection, - cast( - QItemSelectionModel.SelectionFlag, - QItemSelectionModel.SelectCurrent | QItemSelectionModel.Rows, - ), + QItemSelectionModel.SelectionFlag.SelectCurrent + | QItemSelectionModel.SelectionFlag.Rows, ) @@ -630,7 +635,7 @@ class StatusDelegate(QItemDelegate): self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex ) -> None: 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: brush = QBrush(theme_manager.qcolor(row_color)) painter.save() diff --git a/qt/aqt/changenotetype.py b/qt/aqt/changenotetype.py index 89be796fb..d66209931 100644 --- a/qt/aqt/changenotetype.py +++ b/qt/aqt/changenotetype.py @@ -43,7 +43,7 @@ class ChangeNotetypeDialog(QDialog): self.show() 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.setMinimumWidth(400) disable_help_button(self) diff --git a/qt/aqt/clayout.py b/qt/aqt/clayout.py index a499c5f42..ca081af87 100644 --- a/qt/aqt/clayout.py +++ b/qt/aqt/clayout.py @@ -45,7 +45,7 @@ class CardLayout(QDialog): parent: Optional[QWidget] = None, fill_empty: bool = False, ) -> 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) self.mw = aqt.mw self.note = note @@ -80,7 +80,7 @@ class CardLayout(QDialog): self.redraw_everything() restoreGeom(self, "CardLayout") restoreSplitter(self.mainArea, "CardLayoutMainArea") - self.setWindowModality(Qt.ApplicationModal) + self.setWindowModality(Qt.WindowModality.ApplicationModal) self.show() # take the focus away from the first input area when starting up, # as users tend to accidentally type into the template @@ -108,7 +108,9 @@ class CardLayout(QDialog): def setupTopArea(self) -> None: 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.setupUi(self.topArea) self.topAreaForm.templateOptions.setText( @@ -215,8 +217,8 @@ class CardLayout(QDialog): def setupMainArea(self) -> None: split = self.mainArea = QSplitter() - split.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) - split.setOrientation(Qt.Horizontal) + split.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) + split.setOrientation(Qt.Orientation.Horizontal) left = QWidget() tform = self.tform = aqt.forms.template.Ui_Form() tform.setupUi(left) @@ -305,7 +307,7 @@ class CardLayout(QDialog): if not editor.find(text): # try again from top cursor = editor.textCursor() - cursor.movePosition(QTextCursor.Start) + cursor.movePosition(QTextCursor.MoveOperation.Start) editor.setTextCursor(cursor) if not editor.find(text): tooltip("No matches found.") @@ -752,7 +754,7 @@ class CardLayout(QDialog): if t["did"]: te.setText(self.col.decks.get(t["did"])["name"]) te.selectAll() - bb = QDialogButtonBox(QDialogButtonBox.Close) + bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Close) qconnect(bb.rejected, d.close) l.addWidget(bb) d.setLayout(l) diff --git a/qt/aqt/customstudy.py b/qt/aqt/customstudy.py index 8b056342b..878149e48 100644 --- a/qt/aqt/customstudy.py +++ b/qt/aqt/customstudy.py @@ -30,7 +30,7 @@ class CustomStudy(QDialog): self.created_custom_study = False f.setupUi(self) disable_help_button(self) - self.setWindowModality(Qt.WindowModal) + self.setWindowModality(Qt.WindowModality.WindowModal) self.setupSignals() f.radioNew.click() self.exec() @@ -116,7 +116,7 @@ class CustomStudy(QDialog): f.spin.setValue(sval) f.preSpin.setText(pre) f.postSpin.setText(post) - f.buttonBox.button(QDialogButtonBox.Ok).setText(ok) + f.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setText(ok) self.radioIdx = idx def accept(self) -> None: diff --git a/qt/aqt/deckconf.py b/qt/aqt/deckconf.py index c7d5ac753..40432613f 100644 --- a/qt/aqt/deckconf.py +++ b/qt/aqt/deckconf.py @@ -40,13 +40,15 @@ class DeckConf(QDialog): self.mw.checkpoint(tr.actions_options()) self.setupCombos() self.setupConfs() - self.setWindowModality(Qt.WindowModal) + self.setWindowModality(Qt.WindowModality.WindowModal) qconnect( self.form.buttonBox.helpRequested, lambda: openHelp(HelpPage.DECK_OPTIONS) ) qconnect(self.form.confOpts.clicked, self.confOpts) qconnect( - self.form.buttonBox.button(QDialogButtonBox.RestoreDefaults).clicked, + self.form.buttonBox.button( + QDialogButtonBox.StandardButton.RestoreDefaults + ).clicked, self.onRestore, ) self.setWindowTitle( diff --git a/qt/aqt/deckdescription.py b/qt/aqt/deckdescription.py index 064883613..ccd534601 100644 --- a/qt/aqt/deckdescription.py +++ b/qt/aqt/deckdescription.py @@ -17,7 +17,7 @@ class DeckDescriptionDialog(QDialog): silentlyClose = True def __init__(self, mw: aqt.main.AnkiQt) -> None: - QDialog.__init__(self, mw, Qt.Window) + QDialog.__init__(self, mw, Qt.WindowType.Window) self.mw = mw # set on success @@ -39,7 +39,7 @@ class DeckDescriptionDialog(QDialog): def _setup_ui(self) -> None: self.setWindowTitle(tr.scheduling_description()) - self.setWindowModality(Qt.ApplicationModal) + self.setWindowModality(Qt.WindowModality.ApplicationModal) self.mw.garbage_collect_on_dialog_finish(self) self.setMinimumWidth(400) disable_help_button(self) @@ -58,7 +58,7 @@ class DeckDescriptionDialog(QDialog): box.addWidget(self.description) button_box = QDialogButtonBox() - ok = button_box.addButton(QDialogButtonBox.Ok) + ok = button_box.addButton(QDialogButtonBox.StandardButton.Ok) qconnect(ok.clicked, self.save_and_accept) box.addWidget(button_box) diff --git a/qt/aqt/deckoptions.py b/qt/aqt/deckoptions.py index 3a89969d0..76bf44dcb 100644 --- a/qt/aqt/deckoptions.py +++ b/qt/aqt/deckoptions.py @@ -28,14 +28,14 @@ class DeckOptionsDialog(QDialog): silentlyClose = True 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._deck = deck self._setup_ui() self.show() def _setup_ui(self) -> None: - self.setWindowModality(Qt.ApplicationModal) + self.setWindowModality(Qt.WindowModality.ApplicationModal) self.mw.garbage_collect_on_dialog_finish(self) self.setMinimumWidth(400) disable_help_button(self) diff --git a/qt/aqt/editcurrent.py b/qt/aqt/editcurrent.py index fa934f305..4d841b5bc 100644 --- a/qt/aqt/editcurrent.py +++ b/qt/aqt/editcurrent.py @@ -12,7 +12,7 @@ from aqt.utils import disable_help_button, restoreGeom, saveGeom, tr class EditCurrent(QDialog): 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) self.mw = mw self.form = aqt.forms.editcurrent.Ui_Dialog() @@ -21,7 +21,7 @@ class EditCurrent(QDialog): disable_help_button(self) self.setMinimumHeight(400) self.setMinimumWidth(250) - self.form.buttonBox.button(QDialogButtonBox.Close).setShortcut( + self.form.buttonBox.button(QDialogButtonBox.StandardButton.Close).setShortcut( QKeySequence("Ctrl+Return") ) self.editor = aqt.editor.Editor(self.mw, self.form.fieldsArea, self) diff --git a/qt/aqt/editor.py b/qt/aqt/editor.py index 5fce6df39..620802ed4 100644 --- a/qt/aqt/editor.py +++ b/qt/aqt/editor.py @@ -902,7 +902,7 @@ $editorToolbar.then(({{ toolbar }}) => toolbar.appendGroup({{ @deprecated(info=_js_legacy) 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.setupUi(d) restoreGeom(d, "htmlEditor") @@ -911,11 +911,11 @@ $editorToolbar.then(({{ toolbar }}) => toolbar.appendGroup({{ form.buttonBox.helpRequested, lambda: openHelp(HelpPage.EDITING_FEATURES) ) font = QFont("Courier") - font.setStyleHint(QFont.TypeWriter) + font.setStyleHint(QFont.StyleHint.TypeWriter) form.textEdit.setFont(font) form.textEdit.setPlainText(self.note.fields[field]) d.show() - form.textEdit.moveCursor(QTextCursor.End) + form.textEdit.moveCursor(QTextCursor.MoveOperation.End) d.exec() html = form.textEdit.toPlainText() if html.find(">") > -1: @@ -997,7 +997,10 @@ $editorToolbar.then(({{ toolbar }}) => toolbar.appendGroup({{ def onChangeCol(self) -> None: if isLin: new = QColorDialog.getColor( - QColor(self.fcolour), None, None, QColorDialog.DontUseNativeDialog + QColor(self.fcolour), + None, + None, + QColorDialog.ColorDialogOption.DontUseNativeDialog, ) else: new = QColorDialog.getColor(QColor(self.fcolour), None) @@ -1118,10 +1121,10 @@ class EditorWebView(AnkiWebView): self._flagAnkiText() def onCut(self) -> None: - self.triggerPageAction(QWebEnginePage.Cut) + self.triggerPageAction(QWebEnginePage.WebAction.Cut) def onCopy(self) -> None: - self.triggerPageAction(QWebEnginePage.Copy) + self.triggerPageAction(QWebEnginePage.WebAction.Copy) def _wantsExtendedPaste(self) -> bool: strip_html = self.editor.mw.col.get_config_bool( @@ -1140,10 +1143,10 @@ class EditorWebView(AnkiWebView): self.editor.doPaste(html, internal, extended) def onPaste(self) -> None: - self._onPaste(QClipboard.Clipboard) + self._onPaste(QClipboard.Mode.Clipboard) def onMiddleClickPaste(self) -> None: - self._onPaste(QClipboard.Selection) + self._onPaste(QClipboard.Mode.Selection) def dragEnterEvent(self, evt: QDragEnterEvent) -> None: evt.accept() diff --git a/qt/aqt/emptycards.py b/qt/aqt/emptycards.py index a84bc309f..1048caddd 100644 --- a/qt/aqt/emptycards.py +++ b/qt/aqt/emptycards.py @@ -63,7 +63,7 @@ class EmptyCardsDialog(QDialog): qconnect(self.finished, on_finished) 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) qconnect(self._delete_button.clicked, self._on_delete) diff --git a/qt/aqt/exporting.py b/qt/aqt/exporting.py index dbcdf6260..7fbfbe001 100644 --- a/qt/aqt/exporting.py +++ b/qt/aqt/exporting.py @@ -31,7 +31,7 @@ class ExportDialog(QDialog): did: DeckId | None = None, cids: list[CardId] | None = None, ): - QDialog.__init__(self, mw, Qt.Window) + QDialog.__init__(self, mw, Qt.WindowType.Window) self.mw = mw self.col = mw.col.weakref() self.frm = aqt.forms.exporting.Ui_ExportDialog() @@ -64,7 +64,7 @@ class ExportDialog(QDialog): self.frm.deck.addItems(self.decks) # save button 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 if did: name = self.mw.col.decks.get(did)["name"] diff --git a/qt/aqt/fields.py b/qt/aqt/fields.py index 9048e935e..00155a79b 100644 --- a/qt/aqt/fields.py +++ b/qt/aqt/fields.py @@ -45,13 +45,19 @@ class FieldDialog(QDialog): without_unicode_isolation(tr.fields_fields_for(val=self.model["name"])) ) disable_help_button(self) - self.form.buttonBox.button(QDialogButtonBox.Help).setAutoDefault(False) - self.form.buttonBox.button(QDialogButtonBox.Cancel).setAutoDefault(False) - self.form.buttonBox.button(QDialogButtonBox.Save).setAutoDefault(False) + self.form.buttonBox.button(QDialogButtonBox.StandardButton.Help).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.fillFields() 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.setCurrentRow(open_at) self.exec() @@ -77,15 +83,21 @@ class FieldDialog(QDialog): def onDrop(self, ev: QDropEvent) -> None: fieldList = self.form.fieldList 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 if dropPos == idx: return - if indicatorPos == QAbstractItemView.OnViewport: # to bottom. + if ( + indicatorPos == QAbstractItemView.DropIndicatorPosition.OnViewport + ): # to bottom. movePos = fieldList.count() - 1 - elif indicatorPos == QAbstractItemView.AboveItem: + elif indicatorPos == QAbstractItemView.DropIndicatorPosition.AboveItem: movePos = dropPos - elif indicatorPos == QAbstractItemView.BelowItem: + elif indicatorPos == QAbstractItemView.DropIndicatorPosition.BelowItem: movePos = dropPos + 1 # the item in idx is removed thus subtract 1. if idx < dropPos: diff --git a/qt/aqt/filtered_deck.py b/qt/aqt/filtered_deck.py index 1876521ba..e225cb0e7 100644 --- a/qt/aqt/filtered_deck.py +++ b/qt/aqt/filtered_deck.py @@ -90,7 +90,7 @@ class FilteredDeckConfigDialog(QDialog): QPushButton[label="hint"] {{ color: {grey} }}""" ) disable_help_button(self) - self.setWindowModality(Qt.WindowModal) + self.setWindowModality(Qt.WindowModality.WindowModal) qconnect( self.form.buttonBox.helpRequested, lambda: openHelp(HelpPage.FILTERED_DECK) ) @@ -117,7 +117,9 @@ class FilteredDeckConfigDialog(QDialog): build_label = tr.actions_rebuild() else: 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) self._onReschedToggled(0) diff --git a/qt/aqt/forms/findreplace.ui b/qt/aqt/forms/findreplace.ui index 8d08770ab..ec11bbc24 100644 --- a/qt/aqt/forms/findreplace.ui +++ b/qt/aqt/forms/findreplace.ui @@ -6,8 +6,8 @@ 0 0 - 377 - 224 + 479 + 247 @@ -31,7 +31,7 @@ QComboBox::NoInsert - QComboBox::AdjustToMinimumContentsLength + QComboBox::AdjustToMinimumContentsLengthWithIcon @@ -59,7 +59,7 @@ - QComboBox::AdjustToMinimumContentsLength + QComboBox::AdjustToMinimumContentsLengthWithIcon @@ -95,7 +95,7 @@ QComboBox::NoInsert - QComboBox::AdjustToMinimumContentsLength + QComboBox::AdjustToMinimumContentsLengthWithIcon diff --git a/qt/aqt/importing.py b/qt/aqt/importing.py index 46f852e3d..7260ac16f 100644 --- a/qt/aqt/importing.py +++ b/qt/aqt/importing.py @@ -35,7 +35,7 @@ from aqt.utils import ( class ChangeMap(QDialog): 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.model = model self.frm = aqt.forms.changemap.Ui_ChangeMap() @@ -85,13 +85,14 @@ class ImportDialog(QDialog): _DEFAULT_FILE_DELIMITER = "\t" 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.importer = importer self.frm = aqt.forms.importing.Ui_ImportDialog() self.frm.setupUi(self) qconnect( - self.frm.buttonBox.button(QDialogButtonBox.Help).clicked, self.helpRequested + self.frm.buttonBox.button(QDialogButtonBox.StandardButton.Help).clicked, + self.helpRequested, ) disable_help_button(self) self.setupMappingFrame() @@ -108,7 +109,7 @@ class ImportDialog(QDialog): self.frm.tagModified.setCol(self.mw.col) # import button b = QPushButton(tr.actions_import()) - self.frm.buttonBox.addButton(b, QDialogButtonBox.AcceptRole) + self.frm.buttonBox.addButton(b, QDialogButtonBox.ButtonRole.AcceptRole) self.exec() def setupOptions(self) -> None: diff --git a/qt/aqt/main.py b/qt/aqt/main.py index 967819ff8..1249e764f 100644 --- a/qt/aqt/main.py +++ b/qt/aqt/main.py @@ -107,10 +107,7 @@ class AnkiQt(QMainWindow): self.pm = profileManager # init rest of app self.safeMode = ( - bool( - cast(Qt.KeyboardModifier, self.app.queryKeyboardModifiers()) - & Qt.ShiftModifier - ) + bool(self.app.queryKeyboardModifiers() & Qt.KeyboardModifier.ShiftModifier) or self.opts.safemode ) try: @@ -817,15 +814,15 @@ title="{}" {}>{}""".format( self.form.setupUi(self) # 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) # main area self.web = aqt.webview.AnkiWebView(title="main webview") - self.web.setFocusPolicy(Qt.WheelFocus) + self.web.setFocusPolicy(Qt.FocusPolicy.WheelFocus) self.web.setMinimumWidth(400) # bottom area sweb = self.bottomWeb = aqt.webview.AnkiWebView(title="bottom toolbar") - sweb.setFocusPolicy(Qt.WheelFocus) + sweb.setFocusPolicy(Qt.FocusPolicy.WheelFocus) # add in a layout self.mainLayout = QVBoxLayout() self.mainLayout.setContentsMargins(0, 0, 0, 0) @@ -991,7 +988,7 @@ title="{}" {}>{}""".format( def raiseMain(self) -> bool: if not self.app.activeWindow(): # make sure window is shown - self.setWindowState(self.windowState() & ~Qt.WindowMinimized) # type: ignore + self.setWindowState(self.windowState() & ~Qt.WindowState.WindowMinimized) # type: ignore return True def setupStyle(self) -> None: @@ -1393,7 +1390,7 @@ title="{}" {}>{}""".format( frm.setupUi(d) restoreGeom(d, "DebugConsoleWindow") restoreSplitter(frm.splitter, "DebugConsoleWindow") - font = QFontDatabase.systemFont(QFontDatabase.FixedFont) + font = QFontDatabase.systemFont(QFontDatabase.SystemFont.FixedFont) font.setPointSize(frm.text.font().pointSize() + 1) frm.text.setFont(font) frm.log.setFont(font) @@ -1485,7 +1482,7 @@ title="{}" {}>{}""".format( def onDebugPrint(self, frm: aqt.forms.debug.Ui_Dialog) -> None: cursor = frm.text.textCursor() position = cursor.position() - cursor.select(QTextCursor.LineUnderCursor) + cursor.select(QTextCursor.SelectionType.LineUnderCursor) line = cursor.selectedText() pfx, sfx = "pp(", ")" if not line.startswith(pfx): @@ -1566,7 +1563,7 @@ title="{}" {}>{}""".format( cast(QAction, action).setStatusTip("") def onMacMinimize(self) -> None: - self.setWindowState(self.windowState() | Qt.WindowMinimized) # type: ignore + self.setWindowState(self.windowState() | Qt.WindowState.WindowMinimized) # type: ignore # Single instance support ########################################################################## @@ -1606,7 +1603,7 @@ title="{}" {}>{}""".format( if isWin: # on windows we can raise the window by minimizing and restoring self.showMinimized() - self.setWindowState(Qt.WindowActive) + self.setWindowState(Qt.WindowState.WindowActive) self.showNormal() else: # on osx we can raise the window. on unity the icon in the tray will just flash. diff --git a/qt/aqt/mediacheck.py b/qt/aqt/mediacheck.py index 299031444..fd58d4274 100644 --- a/qt/aqt/mediacheck.py +++ b/qt/aqt/mediacheck.py @@ -105,33 +105,33 @@ class MediaChecker: text = QPlainTextEdit() text.setReadOnly(True) text.setPlainText(report) - text.setWordWrapMode(QTextOption.NoWrap) + text.setWordWrapMode(QTextOption.WrapMode.NoWrap) layout.addWidget(text) - box = QDialogButtonBox(QDialogButtonBox.Close) + box = QDialogButtonBox(QDialogButtonBox.StandardButton.Close) layout.addWidget(box) if output.unused: b = QPushButton(tr.media_check_delete_unused()) 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)) if output.missing: if any(map(lambda x: x.startswith("latex-"), output.missing)): b = QPushButton(tr.media_check_render_latex()) b.setAutoDefault(False) - box.addButton(b, QDialogButtonBox.RejectRole) + box.addButton(b, QDialogButtonBox.ButtonRole.RejectRole) qconnect(b.clicked, self._on_render_latex) if output.have_trash: b = QPushButton(tr.media_check_empty_trash()) b.setAutoDefault(False) - box.addButton(b, QDialogButtonBox.RejectRole) + box.addButton(b, QDialogButtonBox.ButtonRole.RejectRole) qconnect(b.clicked, lambda c: self._on_empty_trash()) b = QPushButton(tr.media_check_restore_trash()) b.setAutoDefault(False) - box.addButton(b, QDialogButtonBox.RejectRole) + box.addButton(b, QDialogButtonBox.ButtonRole.RejectRole) qconnect(b.clicked, lambda c: self._on_restore_trash()) qconnect(box.rejected, diag.reject) diff --git a/qt/aqt/mediasync.py b/qt/aqt/mediasync.py index 8b8e4a92d..1c5a366ff 100644 --- a/qt/aqt/mediasync.py +++ b/qt/aqt/mediasync.py @@ -162,7 +162,9 @@ class MediaSyncDialog(QDialog): self.abort_button = QPushButton(tr.sync_abort_button()) qconnect(self.abort_button.clicked, self._on_abort) 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()) gui_hooks.media_sync_did_progress.append(self._on_log_entry) @@ -171,7 +173,7 @@ class MediaSyncDialog(QDialog): self.form.plainTextEdit.setPlainText( "\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() def reject(self) -> None: diff --git a/qt/aqt/models.py b/qt/aqt/models.py index e395b3d3d..5904acbda 100644 --- a/qt/aqt/models.py +++ b/qt/aqt/models.py @@ -48,7 +48,7 @@ class Models(QDialog): parent = parent or mw self.fromMain = fromMain 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() assert self.col self.mm = self.col.models @@ -97,7 +97,7 @@ class Models(QDialog): default_buttons.append((tr.notetypes_options(), self.onAdvanced)) 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(f.modelsList.itemDoubleClicked, self.onRename) @@ -235,7 +235,7 @@ class AddModel(QDialog): self.parent_ = parent or mw self.mw = mw self.col = mw.col - QDialog.__init__(self, self.parent_, Qt.Window) + QDialog.__init__(self, self.parent_, Qt.WindowType.Window) self.model = None self.dialog = aqt.forms.addmodel.Ui_Dialog() self.dialog.setupUi(self) diff --git a/qt/aqt/operations/scheduling.py b/qt/aqt/operations/scheduling.py index 52bc95f01..7cfeea6f8 100644 --- a/qt/aqt/operations/scheduling.py +++ b/qt/aqt/operations/scheduling.py @@ -93,7 +93,7 @@ def reposition_new_cards_dialog( d = QDialog(parent) disable_help_button(d) - d.setWindowModality(Qt.WindowModal) + d.setWindowModality(Qt.WindowModality.WindowModal) frm = aqt.forms.reposition.Ui_Dialog() frm.setupUi(d) diff --git a/qt/aqt/preferences.py b/qt/aqt/preferences.py index 6a163df97..1ebb87e4a 100644 --- a/qt/aqt/preferences.py +++ b/qt/aqt/preferences.py @@ -16,14 +16,18 @@ from aqt.utils import HelpPage, disable_help_button, openHelp, showInfo, showWar class Preferences(QDialog): def __init__(self, mw: AnkiQt) -> None: - QDialog.__init__(self, mw, Qt.Window) + QDialog.__init__(self, mw, Qt.WindowType.Window) self.mw = mw self.prof = self.mw.pm.profile self.form = aqt.forms.preferences.Ui_Preferences() self.form.setupUi(self) disable_help_button(self) - self.form.buttonBox.button(QDialogButtonBox.Help).setAutoDefault(False) - self.form.buttonBox.button(QDialogButtonBox.Close).setAutoDefault(False) + self.form.buttonBox.button(QDialogButtonBox.StandardButton.Help).setAutoDefault( + False + ) + self.form.buttonBox.button( + QDialogButtonBox.StandardButton.Close + ).setAutoDefault(False) qconnect( self.form.buttonBox.helpRequested, lambda: openHelp(HelpPage.PREFERENCES) ) diff --git a/qt/aqt/profiles.py b/qt/aqt/profiles.py index 3832dca5f..ce1fabef6 100644 --- a/qt/aqt/profiles.py +++ b/qt/aqt/profiles.py @@ -461,9 +461,9 @@ create table if not exists profiles code = obj[1] name = obj[0] 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()) self.setLang(code) diff --git a/qt/aqt/progress.py b/qt/aqt/progress.py index 2d8b8e290..0e89195e3 100644 --- a/qt/aqt/progress.py +++ b/qt/aqt/progress.py @@ -92,7 +92,7 @@ class ProgressManager: self._win.form.progressBar.setTextVisible(False) self._win.form.label.setText(label) self._win.setWindowTitle("Anki") - self._win.setWindowModality(Qt.ApplicationModal) + self._win.setWindowModality(Qt.WindowModality.ApplicationModal) self._win.setMinimumWidth(300) self._busy_cursor_timer = QTimer(self.mw) self._busy_cursor_timer.setSingleShot(True) @@ -177,7 +177,7 @@ class ProgressManager: elap = time.time() - self._shown if elap >= 0.5: 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 # already been dropped; delete it if it hasn't been if not sip.isdeleted(self._win): @@ -186,7 +186,7 @@ class ProgressManager: self._shown = 0 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: self.app.restoreOverrideCursor() @@ -235,6 +235,6 @@ class ProgressDialog(QDialog): evt.ignore() def keyPressEvent(self, evt: QKeyEvent) -> None: - if evt.key() == Qt.Key_Escape: + if evt.key() == Qt.Key.Key_Escape: evt.ignore() self.wantCancel = True diff --git a/qt/aqt/qt.py b/qt/aqt/qt.py index 1d53b9fcf..541a3fb8c 100644 --- a/qt/aqt/qt.py +++ b/qt/aqt/qt.py @@ -9,14 +9,34 @@ import sys import traceback from typing import Callable, Union -from PyQt5.Qt import * # type: ignore -from PyQt5.QtCore import * -from PyQt5.QtCore import pyqtRemoveInputHook # pylint: disable=no-name-in-module -from PyQt5.QtGui import * # type: ignore -from PyQt5.QtNetwork import QLocalServer, QLocalSocket, QNetworkProxy -from PyQt5.QtWebChannel import QWebChannel -from PyQt5.QtWebEngineWidgets import * -from PyQt5.QtWidgets import * +try: + from PyQt6 import sip + from PyQt6.QtCore import * + + # conflicting Qt and qFuzzyCompare definitions require an ignore + from PyQt6.QtGui import * # type: ignore[misc] + from PyQt6.QtNetwork import QLocalServer, QLocalSocket, QNetworkProxy + 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 @@ -24,12 +44,6 @@ from anki.utils import isMac, isWin os.environ["LIBOVERLAY_SCROLLBAR"] = "0" -try: - from PyQt5 import sip -except ImportError: - import sip # type: ignore - - def debug() -> None: from pdb import set_trace diff --git a/qt/aqt/qt5.py b/qt/aqt/qt5.py index 401c1fc1a..927eccbf1 100644 --- a/qt/aqt/qt5.py +++ b/qt/aqt/qt5.py @@ -1,6 +1,8 @@ # Copyright: Ankitects Pty Ltd and contributors # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html +# pylint: skip-file + """ PyQt5-only code """ diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index 31ba40529..afc309655 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -433,11 +433,11 @@ class Reviewer: return [ ("e", self.mw.onEditCurrent), (" ", self.onEnterKey), - (Qt.Key_Return, self.onEnterKey), - (Qt.Key_Enter, self.onEnterKey), + (Qt.Key.Key_Return, self.onEnterKey), + (Qt.Key.Key_Enter, self.onEnterKey), ("m", self.showContextMenu), ("r", self.replayAudio), - (Qt.Key_F5, self.replayAudio), + (Qt.Key.Key_F5, self.replayAudio), *( (f"Ctrl+{flag.index}", self.set_flag_func(flag.index)) for flag in self.mw.flags.all() @@ -875,7 +875,7 @@ time = %(time)d; part2 = tr.studying_minute(count=mins) fin = tr.studying_finish() diag = askUserDialog(f"{part1} {part2}", [tr.studying_continue(), fin]) - diag.setIcon(QMessageBox.Information) + diag.setIcon(QMessageBox.Icon.Information) if diag.run() == fin: self.mw.moveToState("deckBrowser") return True diff --git a/qt/aqt/sound.py b/qt/aqt/sound.py index 3670413b1..b7d3a5c99 100644 --- a/qt/aqt/sound.py +++ b/qt/aqt/sound.py @@ -666,15 +666,18 @@ class RecordDialog(QDialog): hbox.addWidget(self.label) v = QVBoxLayout() v.addLayout(hbox) - buts = QDialogButtonBox.Save | QDialogButtonBox.Cancel + buts = ( + QDialogButtonBox.StandardButton.Save + | QDialogButtonBox.StandardButton.Cancel + ) b = QDialogButtonBox(buts) # type: ignore v.addWidget(b) self.setLayout(v) - save_button = b.button(QDialogButtonBox.Save) + save_button = b.button(QDialogButtonBox.StandardButton.Save) save_button.setDefault(True) save_button.setAutoDefault(True) 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.setAutoDefault(False) qconnect(cancel_button.clicked, self.reject) diff --git a/qt/aqt/stats.py b/qt/aqt/stats.py index 755a3d355..cd2b32d5d 100644 --- a/qt/aqt/stats.py +++ b/qt/aqt/stats.py @@ -25,7 +25,7 @@ class NewDeckStats(QDialog): """New deck stats.""" 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) self.mw = mw self.name = "deckStats" @@ -40,7 +40,9 @@ class NewDeckStats(QDialog): f.groupBox.setVisible(False) f.groupBox_2.setVisible(False) 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) b.setAutoDefault(False) maybeHideClose(self.form.buttonBox) @@ -104,7 +106,7 @@ class DeckStats(QDialog): """Legacy deck stats, used by some add-ons.""" 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) self.mw = mw self.name = "deckStats" @@ -123,7 +125,9 @@ class DeckStats(QDialog): self.setStyleSheet("QGroupBox { border: 0; }") f.setupUi(self) 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) b.setAutoDefault(False) qconnect(f.groups.clicked, lambda: self.changeScope("deck")) diff --git a/qt/aqt/studydeck.py b/qt/aqt/studydeck.py index 7403e6437..adc432ca1 100644 --- a/qt/aqt/studydeck.py +++ b/qt/aqt/studydeck.py @@ -49,18 +49,18 @@ class StudyDeck(QDialog): disable_help_button(self) if not cancel: self.form.buttonBox.removeButton( - self.form.buttonBox.button(QDialogButtonBox.Cancel) + self.form.buttonBox.button(QDialogButtonBox.StandardButton.Cancel) ) if buttons is not None: for button_or_label in buttons: self.form.buttonBox.addButton( - button_or_label, QDialogButtonBox.ActionRole + button_or_label, QDialogButtonBox.ButtonRole.ActionRole ) else: b = QPushButton(tr.actions_add()) b.setShortcut(QKeySequence("Ctrl+N")) 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) if title: self.setWindowTitle(title) @@ -78,9 +78,9 @@ class StudyDeck(QDialog): self.origNames = names() self.name: Optional[str] = None 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.filter.textEdited, self.redraw) qconnect(self.form.list.itemDoubleClicked, self.accept) @@ -90,20 +90,20 @@ class StudyDeck(QDialog): self.exec() 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() rows_count = self.form.list.count() key = evt.key() - if key == Qt.Key_Up: + if key == Qt.Key.Key_Up: new_row = current_row - 1 - elif key == Qt.Key_Down: + elif key == Qt.Key.Key_Down: new_row = current_row + 1 elif ( - int(evt.modifiers()) & Qt.ControlModifier - and Qt.Key_1 <= key <= Qt.Key_9 + evt.modifiers() & Qt.KeyboardModifier.ControlModifier + 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: new_row = row_index @@ -126,7 +126,7 @@ class StudyDeck(QDialog): else: idx = 0 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: name = name.lower() diff --git a/qt/aqt/switch.py b/qt/aqt/switch.py index f9ad05343..2d8a610e1 100644 --- a/qt/aqt/switch.py +++ b/qt/aqt/switch.py @@ -28,7 +28,7 @@ class Switch(QAbstractButton): super().__init__(parent=parent) self.setCheckable(True) super().setChecked(False) - self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + self.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) self._left_label = left_label self._right_label = right_label self._left_color = left_color @@ -76,8 +76,8 @@ class Switch(QAbstractButton): def paintEvent(self, _event: QPaintEvent) -> None: painter = QPainter(self) - painter.setRenderHint(QPainter.Antialiasing, True) - painter.setPen(Qt.NoPen) + painter.setRenderHint(QPainter.RenderHint.Antialiasing, True) + painter.setPen(Qt.PenStyle.NoPen) self._paint_path(painter) self._paint_knob(painter) self._paint_label(painter) @@ -113,15 +113,17 @@ class Switch(QAbstractButton): font = painter.font() font.setPixelSize(int(1.2 * self._knob_radius)) 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: super().mouseReleaseEvent(event) - if event.button() == Qt.LeftButton: + if event.button() == Qt.MouseButton.LeftButton: self._animate_toggle() - def enterEvent(self, event: QEvent) -> None: - self.setCursor(Qt.PointingHandCursor) + def enterEvent(self, event: QEnterEvent) -> None: + self.setCursor(Qt.CursorShape.PointingHandCursor) super().enterEvent(event) def toggle(self) -> None: diff --git a/qt/aqt/sync.py b/qt/aqt/sync.py index f84df9ce8..2da20d933 100644 --- a/qt/aqt/sync.py +++ b/qt/aqt/sync.py @@ -292,7 +292,7 @@ def get_id_and_pass_from_user( diag = QDialog(mw) diag.setWindowTitle("Anki") disable_help_button(diag) - diag.setWindowModality(Qt.WindowModal) + diag.setWindowModality(Qt.WindowModality.WindowModal) vbox = QVBoxLayout() info_label = QLabel( without_unicode_isolation( @@ -313,11 +313,11 @@ def get_id_and_pass_from_user( g.addWidget(l2, 1, 0) passwd = QLineEdit() passwd.setText(password) - passwd.setEchoMode(QLineEdit.Password) + passwd.setEchoMode(QLineEdit.EchoMode.Password) g.addWidget(passwd, 1, 1) vbox.addLayout(g) - bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) # type: ignore - bb.button(QDialogButtonBox.Ok).setAutoDefault(True) + bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) # type: ignore + bb.button(QDialogButtonBox.StandardButton.Ok).setAutoDefault(True) qconnect(bb.accepted, diag.accept) qconnect(bb.rejected, diag.reject) vbox.addWidget(bb) diff --git a/qt/aqt/tagedit.py b/qt/aqt/tagedit.py index 69c31d320..90cbf56ed 100644 --- a/qt/aqt/tagedit.py +++ b/qt/aqt/tagedit.py @@ -26,9 +26,9 @@ class TagEdit(QLineEdit): self._completer = TagCompleter(self.model, parent, self) else: self._completer = QCompleter(self.model, parent) - self._completer.setCompletionMode(QCompleter.PopupCompletion) - self._completer.setCaseSensitivity(Qt.CaseInsensitive) - self._completer.setFilterMode(Qt.MatchContains) + self._completer.setCompletionMode(QCompleter.CompletionMode.PopupCompletion) + self._completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive) + self._completer.setFilterMode(Qt.MatchFlag.MatchContains) self.setCompleter(self._completer) def setCol(self, col: Collection) -> None: @@ -45,12 +45,15 @@ class TagEdit(QLineEdit): QLineEdit.focusInEvent(self, evt) 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 if not self._completer.popup().isVisible(): self.showCompleter() 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 if not self._completer.popup().isVisible(): self.showCompleter() @@ -61,7 +64,7 @@ class TagEdit(QLineEdit): self._completer.setCurrentRow(0) return 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() ): # apply first completion if no suggestion selected @@ -78,13 +81,13 @@ class TagEdit(QLineEdit): # if it's a modifier, don't show return if evt.key() not in ( - Qt.Key_Enter, - Qt.Key_Return, - Qt.Key_Escape, - Qt.Key_Space, - Qt.Key_Tab, - Qt.Key_Backspace, - Qt.Key_Delete, + Qt.Key.Key_Enter, + Qt.Key.Key_Return, + Qt.Key.Key_Escape, + Qt.Key.Key_Space, + Qt.Key.Key_Tab, + Qt.Key.Key_Backspace, + Qt.Key.Key_Delete, ): self.showCompleter() gui_hooks.tag_editor_did_process_key(self, evt) diff --git a/qt/aqt/taglimit.py b/qt/aqt/taglimit.py index 1affd4550..0a04ef3ad 100644 --- a/qt/aqt/taglimit.py +++ b/qt/aqt/taglimit.py @@ -13,7 +13,7 @@ from aqt.utils import disable_help_button, restoreGeom, saveGeom, showWarning, t class TagLimit(QDialog): 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_list: list[str] = [] self.mw = mw @@ -23,11 +23,15 @@ class TagLimit(QDialog): self.dialog.setupUi(self) disable_help_button(self) 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) 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) self.rebuildTagList() @@ -54,19 +58,19 @@ class TagLimit(QDialog): item = QListWidgetItem(t.replace("_", " ")) self.dialog.activeList.addItem(item) if t in yesHash: - mode = QItemSelectionModel.Select + mode = QItemSelectionModel.SelectionFlag.Select self.dialog.activeCheck.setChecked(True) else: - mode = QItemSelectionModel.Deselect + mode = QItemSelectionModel.SelectionFlag.Deselect idx = self.dialog.activeList.indexFromItem(item) self.dialog.activeList.selectionModel().select(idx, mode) # inactive item = QListWidgetItem(t.replace("_", " ")) self.dialog.inactiveList.addItem(item) if t in noHash: - mode = QItemSelectionModel.Select + mode = QItemSelectionModel.SelectionFlag.Select else: - mode = QItemSelectionModel.Deselect + mode = QItemSelectionModel.SelectionFlag.Deselect idx = self.dialog.inactiveList.indexFromItem(item) self.dialog.inactiveList.selectionModel().select(idx, mode) diff --git a/qt/aqt/theme.py b/qt/aqt/theme.py index 5148b8228..f95799d50 100644 --- a/qt/aqt/theme.py +++ b/qt/aqt/theme.py @@ -92,7 +92,9 @@ class ThemeManager: icon = QIcon(path.path) pixmap = icon.pixmap(16) 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.end() icon = QIcon(pixmap) @@ -207,34 +209,44 @@ QTabWidget {{ background-color: {}; }} palette = QPalette() text_fg = self.qcolor(colors.TEXT_FG) - palette.setColor(QPalette.WindowText, text_fg) - palette.setColor(QPalette.ToolTipText, text_fg) - palette.setColor(QPalette.Text, text_fg) - palette.setColor(QPalette.ButtonText, text_fg) + palette.setColor(QPalette.ColorRole.WindowText, text_fg) + palette.setColor(QPalette.ColorRole.ToolTipText, text_fg) + palette.setColor(QPalette.ColorRole.Text, text_fg) + palette.setColor(QPalette.ColorRole.ButtonText, text_fg) hlbg = self.qcolor(colors.HIGHLIGHT_BG) hlbg.setAlpha(64) - palette.setColor(QPalette.HighlightedText, self.qcolor(colors.HIGHLIGHT_FG)) - palette.setColor(QPalette.Highlight, hlbg) + palette.setColor( + QPalette.ColorRole.HighlightedText, self.qcolor(colors.HIGHLIGHT_FG) + ) + palette.setColor(QPalette.ColorRole.Highlight, hlbg) window_bg = self.qcolor(colors.WINDOW_BG) - palette.setColor(QPalette.Window, window_bg) - palette.setColor(QPalette.AlternateBase, window_bg) + palette.setColor(QPalette.ColorRole.Window, 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) - palette.setColor(QPalette.Base, frame_bg) - palette.setColor(QPalette.ToolTipBase, frame_bg) + palette.setColor(QPalette.ColorRole.Base, frame_bg) + palette.setColor(QPalette.ColorRole.ToolTipBase, frame_bg) disabled_color = self.qcolor(colors.DISABLED) - palette.setColor(QPalette.Disabled, QPalette.Text, disabled_color) - palette.setColor(QPalette.Disabled, QPalette.ButtonText, disabled_color) - palette.setColor(QPalette.Disabled, QPalette.HighlightedText, disabled_color) + palette.setColor( + QPalette.ColorGroup.Disabled, QPalette.ColorRole.Text, 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) diff --git a/qt/aqt/update.py b/qt/aqt/update.py index 912c0beae..4b5a00fbd 100644 --- a/qt/aqt/update.py +++ b/qt/aqt/update.py @@ -59,17 +59,17 @@ class LatestVersionFinder(QThread): def askAndUpdate(mw: aqt.AnkiQt, ver: str) -> None: baseStr = tr.qt_misc_anki_updatedanki_has_been_released(val=ver) msg = QMessageBox(mw) - msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) # type: ignore - msg.setIcon(QMessageBox.Information) + msg.setStandardButtons(QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No) # type: ignore + msg.setIcon(QMessageBox.Icon.Information) msg.setText(baseStr + tr.qt_misc_would_you_like_to_download_it()) button = QPushButton(tr.qt_misc_ignore_this_update()) - msg.addButton(button, QMessageBox.RejectRole) - msg.setDefaultButton(QMessageBox.Yes) + msg.addButton(button, QMessageBox.ButtonRole.RejectRole) + msg.setDefaultButton(QMessageBox.StandardButton.Yes) ret = msg.exec() if msg.clickedButton() == button: # ignore this update mw.pm.meta["suppressUpdate"] = ver - elif ret == QMessageBox.Yes: + elif ret == QMessageBox.StandardButton.Yes: openLink(aqt.appWebsite) diff --git a/qt/aqt/utils.py b/qt/aqt/utils.py index 1aa282820..3d8dd4120 100644 --- a/qt/aqt/utils.py +++ b/qt/aqt/utils.py @@ -7,7 +7,7 @@ import re import subprocess import sys from functools import wraps -from typing import TYPE_CHECKING, Any, Literal, Sequence, cast +from typing import TYPE_CHECKING, Any, Literal, Sequence import aqt from anki.collection import Collection, HelpPage @@ -96,16 +96,16 @@ def showInfo( else: parent_widget = parent if type == "warning": - icon = QMessageBox.Warning + icon = QMessageBox.Icon.Warning elif type == "critical": - icon = QMessageBox.Critical + icon = QMessageBox.Icon.Critical else: - icon = QMessageBox.Information + icon = QMessageBox.Icon.Information mb = QMessageBox(parent_widget) # if textFormat == "plain": - mb.setTextFormat(Qt.PlainText) + mb.setTextFormat(Qt.TextFormat.PlainText) elif textFormat == "rich": - mb.setTextFormat(Qt.RichText) + mb.setTextFormat(Qt.TextFormat.RichText) elif textFormat is not None: raise Exception("unexpected textFormat type") mb.setText(text) @@ -119,10 +119,10 @@ def showInfo( default = b mb.setDefaultButton(default) else: - b = mb.addButton(QMessageBox.Ok) + b = mb.addButton(QMessageBox.StandardButton.Ok) b.setDefault(True) if help: - b = mb.addButton(QMessageBox.Help) + b = mb.addButton(QMessageBox.StandardButton.Help) qconnect(b.clicked, lambda: openHelp(help)) b.setAutoDefault(False) return mb.exec() @@ -152,7 +152,7 @@ def showText( # used by the importer text = QPlainTextEdit() text.setReadOnly(True) - text.setWordWrapMode(QTextOption.NoWrap) + text.setWordWrapMode(QTextOption.WrapMode.NoWrap) text.setPlainText(txt) else: text = QTextBrowser() @@ -162,7 +162,7 @@ def showText( else: text.setHtml(txt) layout.addWidget(text) - box = QDialogButtonBox(QDialogButtonBox.Close) + box = QDialogButtonBox(QDialogButtonBox.StandardButton.Close) layout.addWidget(box) if copyBtn: @@ -171,7 +171,7 @@ def showText( btn = QPushButton(tr.qt_misc_copy_to_clipboard()) qconnect(btn.clicked, onCopy) - box.addButton(btn, QDialogButtonBox.ActionRole) + box.addButton(btn, QDialogButtonBox.ButtonRole.ActionRole) def onReject() -> None: if geomKey: @@ -209,20 +209,20 @@ def askUser( parent = aqt.mw.app.activeWindow() if not msgfunc: msgfunc = QMessageBox.question - sb = QMessageBox.Yes | QMessageBox.No + sb = QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No if help: - sb |= QMessageBox.Help + sb |= QMessageBox.StandardButton.Help while 1: if defaultno: - default = QMessageBox.No + default = QMessageBox.StandardButton.No else: - default = QMessageBox.Yes - r = msgfunc(parent, title, text, cast(QMessageBox.StandardButtons, sb), default) - if r == QMessageBox.Help: + default = QMessageBox.StandardButton.Yes + r = msgfunc(parent, title, text, sb, default) + if r == QMessageBox.StandardButton.Help: openHelp(help) else: break - return r == QMessageBox.Yes + return r == QMessageBox.StandardButton.Yes class ButtonedDialog(QMessageBox): @@ -238,12 +238,12 @@ class ButtonedDialog(QMessageBox): self._buttons: list[QPushButton] = [] self.setWindowTitle(title) self.help = help - self.setIcon(QMessageBox.Warning) + self.setIcon(QMessageBox.Icon.Warning) self.setText(text) for b in buttons: - self._buttons.append(self.addButton(b, QMessageBox.AcceptRole)) + self._buttons.append(self.addButton(b, QMessageBox.ButtonRole.AcceptRole)) if help: - self.addButton(tr.actions_help(), QMessageBox.HelpRole) + self.addButton(tr.actions_help(), QMessageBox.ButtonRole.HelpRole) buttons.append(tr.actions_help()) def run(self) -> str: @@ -300,16 +300,21 @@ class GetTextDialog(QDialog): self.l.setText(default) self.l.selectAll() v.addWidget(self.l) - buts = QDialogButtonBox.Ok | QDialogButtonBox.Cancel + buts = ( + QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel + ) if help: - buts |= QDialogButtonBox.Help + buts |= QDialogButtonBox.StandardButton.Help b = QDialogButtonBox(buts) # type: ignore v.addWidget(b) self.setLayout(v) - qconnect(b.button(QDialogButtonBox.Ok).clicked, self.accept) - qconnect(b.button(QDialogButtonBox.Cancel).clicked, self.reject) + qconnect(b.button(QDialogButtonBox.StandardButton.Ok).clicked, self.accept) + qconnect(b.button(QDialogButtonBox.StandardButton.Cancel).clicked, self.reject) if help: - qconnect(b.button(QDialogButtonBox.Help).clicked, self.helpRequested) + qconnect( + b.button(QDialogButtonBox.StandardButton.Help).clicked, + self.helpRequested, + ) def accept(self) -> None: return QDialog.accept(self) @@ -337,7 +342,7 @@ def getText( d = GetTextDialog( parent, prompt, help=help, edit=edit, default=default, title=title, **kwargs ) - d.setWindowModality(Qt.WindowModal) + d.setWindowModality(Qt.WindowModality.WindowModal) if geomKey: restoreGeom(d, geomKey) ret = d.exec() @@ -363,7 +368,7 @@ def chooseList( parent = aqt.mw.app.activeWindow() d = QDialog(parent) disable_help_button(d) - d.setWindowModality(Qt.WindowModal) + d.setWindowModality(Qt.WindowModality.WindowModal) l = QVBoxLayout() d.setLayout(l) t = QLabel(prompt) @@ -372,7 +377,7 @@ def chooseList( c.addItems(choices) c.setCurrentRow(startrow) l.addWidget(c) - bb = QDialogButtonBox(QDialogButtonBox.Ok) + bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok) qconnect(bb.accepted, d.accept) l.addWidget(bb) d.exec() @@ -393,9 +398,9 @@ def getTag( def disable_help_button(widget: QWidget) -> None: "Disable the help button in the window titlebar." - flags_int = int(widget.windowFlags()) & ~Qt.WindowContextHelpButtonHint - flags = Qt.WindowFlags(flags_int) # type: ignore - widget.setWindowFlags(flags) + widget.setWindowFlags( + widget.windowFlags() & ~Qt.WindowType.WindowContextHelpButtonHint + ) # File handling @@ -420,7 +425,11 @@ def getFile( else: dirkey = None d = QFileDialog(parent) - mode = QFileDialog.ExistingFiles if multi else QFileDialog.ExistingFile + mode = ( + QFileDialog.FileMode.ExistingFiles + if multi + else QFileDialog.FileMode.ExistingFile + ) d.setFileMode(mode) if os.path.exists(dir): d.setDirectory(dir) @@ -459,7 +468,9 @@ def getSaveFile( variable. The file dialog will default to open with FNAME.""" 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) path = os.path.join(base, fname) file = QFileDialog.getSaveFileName( @@ -467,7 +478,7 @@ def getSaveFile( title, path, f"{key} (*{ext})", - options=QFileDialog.DontConfirmOverwrite, + options=QFileDialog.Option.DontConfirmOverwrite, )[0] if file: # add extension @@ -485,7 +496,7 @@ def getSaveFile( def saveGeom(widget: QWidget, key: str) -> None: key += "Geom" - if isMac and int(widget.windowState()) & Qt.WindowFullScreen: + if isMac and (widget.windowState() & Qt.WindowState.WindowFullScreen): geom = None else: geom = widget.saveGeometry() @@ -646,7 +657,7 @@ def shortcut(key: str) -> str: def maybeHideClose(bbox: QDialogButtonBox) -> None: if isMac: - b = bbox.button(QDialogButtonBox.Close) + b = bbox.button(QDialogButtonBox.StandardButton.Close) if b: bbox.removeButton(b) @@ -706,13 +717,13 @@ def tooltip( """, aw, ) - lab.setFrameStyle(QFrame.Panel) + lab.setFrameStyle(QFrame.Shape.Panel) lab.setLineWidth(2) - lab.setWindowFlags(Qt.ToolTip) + lab.setWindowFlags(Qt.WindowType.ToolTip) if not theme_manager.night_mode: p = QPalette() - p.setColor(QPalette.Window, QColor("#feffc4")) - p.setColor(QPalette.WindowText, QColor("#000000")) + p.setColor(QPalette.ColorRole.Window, QColor("#feffc4")) + p.setColor(QPalette.ColorRole.WindowText, QColor("#000000")) lab.setPalette(p) lab.move(aw.mapToGlobal(QPoint(0 + x_offset, aw.height() - y_offset))) lab.show() @@ -888,7 +899,7 @@ def opengl_vendor() -> str | None: # Can't use versionFunctions there return None - vp = QOpenGLVersionProfile() # type: ignore + vp = QOpenGLVersionProfile() # type: ignore # pylint: disable=undefined-variable vp.setVersion(2, 0) try: @@ -969,16 +980,16 @@ class KeyboardModifiersPressed: def __init__(self) -> None: from aqt import mw - self._modifiers = int(mw.app.keyboardModifiers()) + self._modifiers = mw.app.keyboardModifiers() @property def shift(self) -> bool: - return bool(self._modifiers & Qt.ShiftModifier) + return bool(self._modifiers & Qt.KeyboardModifier.ShiftModifier) @property def control(self) -> bool: - return bool(self._modifiers & Qt.ControlModifier) + return bool(self._modifiers & Qt.KeyboardModifier.ControlModifier) @property def alt(self) -> bool: - return bool(self._modifiers & Qt.AltModifier) + return bool(self._modifiers & Qt.KeyboardModifier.AltModifier) diff --git a/qt/aqt/webview.py b/qt/aqt/webview.py index 9b7399489..72c0cb976 100644 --- a/qt/aqt/webview.py +++ b/qt/aqt/webview.py @@ -48,7 +48,7 @@ class AnkiWebPage(QWebEnginePage): qwebchannel = ":/qtwebchannel/qwebchannel.js" 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) jstext = bytes(cast(bytes, jsfile.readAll())).decode("utf-8") jsfile.close() @@ -74,8 +74,8 @@ class AnkiWebPage(QWebEnginePage): }); """ ) - script.setWorldId(QWebEngineScript.MainWorld) - script.setInjectionPoint(QWebEngineScript.DocumentReady) + script.setWorldId(QWebEngineScript.ScriptWorldId.MainWorld) + script.setInjectionPoint(QWebEngineScript.InjectionPoint.DocumentReady) script.setRunsOnSubFrames(False) self.profile().scripts().insert(script) @@ -92,11 +92,11 @@ class AnkiWebPage(QWebEnginePage): srcID = "" else: srcID = serverbaseurl.sub("", srcID[:80], 1) - if level == QWebEnginePage.InfoMessageLevel: + if level == QWebEnginePage.JavaScriptConsoleMessageLevel.InfoMessageLevel: level_str = "info" - elif level == QWebEnginePage.WarningMessageLevel: + elif level == QWebEnginePage.JavaScriptConsoleMessageLevel.WarningMessageLevel: level_str = "warning" - elif level == QWebEnginePage.ErrorMessageLevel: + elif level == QWebEnginePage.JavaScriptConsoleMessageLevel.ErrorMessageLevel: level_str = "error" else: level_str = str(level) @@ -135,7 +135,9 @@ class AnkiWebPage(QWebEnginePage): # catch buggy links 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") return False # load all other links in browser @@ -240,14 +242,14 @@ class AnkiWebView(QWebEngineView): self.requiresCol = True self.setPage(self._page) - self._page.profile().setHttpCacheType(QWebEngineProfile.NoCache) + self._page.profile().setHttpCacheType(QWebEngineProfile.HttpCacheType.NoCache) self.resetHandlers() self.allowDrops = False self._filterSet = False QShortcut( # type: ignore QKeySequence("Esc"), self, - context=Qt.WidgetWithChildrenShortcut, + context=Qt.ShortcutContext.WidgetWithChildrenShortcut, activated=self.onEsc, ) @@ -258,8 +260,11 @@ class AnkiWebView(QWebEngineView): # disable pinch to zoom gesture if isinstance(evt, QNativeGestureEvent): return True - elif isinstance(evt, QMouseEvent) and evt.type() == QEvent.MouseButtonRelease: - if evt.button() == Qt.MidButton and isLin: + elif ( + isinstance(evt, QMouseEvent) + and evt.type() == QEvent.Type.MouseButtonRelease + ): + if evt.button() == Qt.MouseButton.MiddleButton and isLin: self.onMiddleClickPaste() return True return False @@ -286,19 +291,19 @@ class AnkiWebView(QWebEngineView): w = w.parent() def onCopy(self) -> None: - self.triggerPageAction(QWebEnginePage.Copy) + self.triggerPageAction(QWebEnginePage.WebAction.Copy) def onCut(self) -> None: - self.triggerPageAction(QWebEnginePage.Cut) + self.triggerPageAction(QWebEnginePage.WebAction.Cut) def onPaste(self) -> None: - self.triggerPageAction(QWebEnginePage.Paste) + self.triggerPageAction(QWebEnginePage.WebAction.Paste) def onMiddleClickPaste(self) -> None: - self.triggerPageAction(QWebEnginePage.Paste) + self.triggerPageAction(QWebEnginePage.WebAction.Paste) def onSelectAll(self) -> None: - self.triggerPageAction(QWebEnginePage.SelectAll) + self.triggerPageAction(QWebEnginePage.WebAction.SelectAll) def contextMenuEvent(self, evt: QContextMenuEvent) -> None: m = QMenu(self) @@ -386,11 +391,11 @@ class AnkiWebView(QWebEngineView): # standard palette does not return correct window color on macOS return QColor("#ececec") else: - return theme_manager.default_palette.color(QPalette.Window) + return theme_manager.default_palette.color(QPalette.ColorRole.Window) def standard_css(self) -> str: palette = theme_manager.default_palette - color_hl = palette.color(QPalette.Highlight).name() + color_hl = palette.color(QPalette.ColorRole.Highlight).name() if isWin: # 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 }""" else: family = self.font().family() - color_hl_txt = palette.color(QPalette.HighlightedText).name() - color_btn = palette.color(QPalette.Button).name() + color_hl_txt = palette.color(QPalette.ColorRole.HighlightedText).name() + color_btn = palette.color(QPalette.ColorRole.Button).name() font = f'font-size:14px;font-family:"{family}";' button_style = """ /* Buttons */ diff --git a/qt/dmypy.py b/qt/dmypy.py index 968061146..f8c420c35 100755 --- a/qt/dmypy.py +++ b/qt/dmypy.py @@ -36,7 +36,7 @@ if subprocess.run( os.path.abspath("pip/stubs/extendsitepkgs"), ], 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")), }, cwd=workspace, diff --git a/qt/mypy.ini b/qt/mypy.ini index c8dcf12e9..cff9c7490 100644 --- a/qt/mypy.ini +++ b/qt/mypy.ini @@ -54,6 +54,7 @@ ignore_missing_imports = True ignore_missing_imports = True [mypy-PyQt5.*] ignore_errors = True +ignore_missing_imports = True [mypy-win32com.client] ignore_missing_imports = True [mypy-darkdetect]