From fe2c1510cad7a1afb47b97e0736bce2c249955df Mon Sep 17 00:00:00 2001 From: Evgeny Kulikov <248055+beyondcompute@users.noreply.github.com> Date: Thu, 24 Apr 2025 11:53:01 +0300 Subject: [PATCH] Add Cmd+W close shortcut (on Mac) to more dialogs (#3905) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Enable Cmd+W shortcut in "Edit Current" on Mac * Enable Cmd+W shortcut in "Fields" editor on Mac * Enable Cmd+W shortcut in "Cards" editing on Mac * Enable Cmd+W shortcut in "Sync" tab modal on Mac * Enable Cmd+W shortcut in "Custom Study" tab modal on Mac * Enable Cmd+W shortcut in Settings view on Mac * Enable Cmd+W shortcut in Export dialogs on Mac * Enable Cmd+W shortcut for getText dialog on Mac * Enable Cmd+W shortcut in "Change Deck" on Mac * Enable Cmd+W shortcut in Reposition dialog on Mac * Enable Cmd+W shortcut in "Grade Now" dialog on Mac * Enable Cmd+W shortcut in "Reset…" dialog on Mac * Remove duplicate camelCase variant of add_close_shortcut (dae) - The camelCase variant will remain accessible with a warning. - The removed setattr line is legacy cruft, and wasn't doing anything. --- qt/aqt/addons.py | 4 ++-- qt/aqt/browser/browser.py | 2 ++ qt/aqt/browser/card_info.py | 4 ++-- qt/aqt/changenotetype.py | 4 ++-- qt/aqt/clayout.py | 2 ++ qt/aqt/customstudy.py | 3 ++- qt/aqt/deckdescription.py | 4 ++-- qt/aqt/deckoptions.py | 4 ++-- qt/aqt/editcurrent.py | 3 ++- qt/aqt/exporting.py | 2 ++ qt/aqt/fields.py | 2 ++ qt/aqt/import_export/exporting.py | 2 ++ qt/aqt/import_export/import_dialog.py | 4 ++-- qt/aqt/operations/scheduling.py | 4 +++- qt/aqt/preferences.py | 2 ++ qt/aqt/stats.py | 6 +++--- qt/aqt/studydeck.py | 2 ++ qt/aqt/sync.py | 2 ++ qt/aqt/utils.py | 9 +-------- 19 files changed, 39 insertions(+), 26 deletions(-) diff --git a/qt/aqt/addons.py b/qt/aqt/addons.py index 92965e4e9..fdce9142a 100644 --- a/qt/aqt/addons.py +++ b/qt/aqt/addons.py @@ -40,7 +40,7 @@ from aqt import gui_hooks from aqt.log import ADDON_LOGGER_PREFIX, find_addon_logger, get_addon_logs_folder from aqt.qt import * from aqt.utils import ( - addCloseShortcut, + add_close_shortcut, askUser, disable_help_button, getFile, @@ -829,7 +829,7 @@ class AddonsDialog(QDialog): self.setAcceptDrops(True) self.redrawAddons() restoreGeom(self, "addons") - addCloseShortcut(self) + add_close_shortcut(self) gui_hooks.addons_dialog_will_show(self) self._onAddonSelectionChanged() self.show() diff --git a/qt/aqt/browser/browser.py b/qt/aqt/browser/browser.py index 77a48dbf5..6c1b1486a 100644 --- a/qt/aqt/browser/browser.py +++ b/qt/aqt/browser/browser.py @@ -57,6 +57,7 @@ from aqt.undo import UndoActionsInfo from aqt.utils import ( HelpPage, KeyboardModifiersPressed, + add_close_shortcut, add_ellipsis_to_action_label, current_window, ensure_editor_saved, @@ -1092,6 +1093,7 @@ class Browser(QMainWindow): dialog.setWindowTitle(tr.actions_grade_now()) layout = QHBoxLayout() dialog.setLayout(layout) + add_close_shortcut(dialog) # Add grade buttons for ease, label in [ diff --git a/qt/aqt/browser/card_info.py b/qt/aqt/browser/card_info.py index ff5b69d12..fe031e630 100644 --- a/qt/aqt/browser/card_info.py +++ b/qt/aqt/browser/card_info.py @@ -14,7 +14,7 @@ from anki.errors import NotFoundError from anki.lang import without_unicode_isolation from aqt.qt import * from aqt.utils import ( - addCloseShortcut, + add_close_shortcut, disable_help_button, qconnect, restoreGeom, @@ -53,7 +53,7 @@ class CardInfoDialog(QDialog): self.mw.garbage_collect_on_dialog_finish(self) disable_help_button(self) restoreGeom(self, self.GEOMETRY_KEY, default_size=(800, 800)) - addCloseShortcut(self) + add_close_shortcut(self) setWindowIcon(self) self.web: AnkiWebView | None = AnkiWebView( diff --git a/qt/aqt/changenotetype.py b/qt/aqt/changenotetype.py index 3ab9a87e8..962f49280 100644 --- a/qt/aqt/changenotetype.py +++ b/qt/aqt/changenotetype.py @@ -15,7 +15,7 @@ from anki.notes import NoteId from aqt.operations.notetype import change_notetype_of_notes from aqt.qt import * from aqt.utils import ( - addCloseShortcut, + add_close_shortcut, disable_help_button, restoreGeom, saveGeom, @@ -49,7 +49,7 @@ class ChangeNotetypeDialog(QDialog): self.setMinimumSize(400, 300) disable_help_button(self) restoreGeom(self, self.TITLE, default_size=(800, 800)) - addCloseShortcut(self) + add_close_shortcut(self) self.web = AnkiWebView(kind=AnkiWebViewKind.CHANGE_NOTETYPE) self.web.setVisible(False) diff --git a/qt/aqt/clayout.py b/qt/aqt/clayout.py index 57579d2a8..388ae46c0 100644 --- a/qt/aqt/clayout.py +++ b/qt/aqt/clayout.py @@ -27,6 +27,7 @@ from aqt.sound import av_player, play_clicked_audio from aqt.theme import theme_manager from aqt.utils import ( HelpPage, + add_close_shortcut, ask_user_dialog, askUser, disable_help_button, @@ -90,6 +91,7 @@ class CardLayout(QDialog): gui_hooks.card_layout_will_show(self) self.redraw_everything() restoreGeom(self, "CardLayout") + add_close_shortcut(self) restoreSplitter(self.mainArea, "CardLayoutMainArea") self.setWindowModality(Qt.WindowModality.ApplicationModal) self.show() diff --git a/qt/aqt/customstudy.py b/qt/aqt/customstudy.py index eb8921627..ce4e68a30 100644 --- a/qt/aqt/customstudy.py +++ b/qt/aqt/customstudy.py @@ -15,7 +15,7 @@ from aqt.operations import QueryOp from aqt.operations.scheduling import custom_study from aqt.qt import * from aqt.taglimit import TagLimit -from aqt.utils import disable_help_button, tr +from aqt.utils import add_close_shortcut, disable_help_button, tr RADIO_NEW = 1 RADIO_REV = 2 @@ -63,6 +63,7 @@ class CustomStudy(QDialog): self.form.setupUi(self) disable_help_button(self) self.setupSignals() + add_close_shortcut(self) self.form.radioNew.click() self.open() diff --git a/qt/aqt/deckdescription.py b/qt/aqt/deckdescription.py index 261f52ea2..e218c0a79 100644 --- a/qt/aqt/deckdescription.py +++ b/qt/aqt/deckdescription.py @@ -10,7 +10,7 @@ from anki.decks import DeckDict from aqt.operations import QueryOp from aqt.operations.deck import update_deck_dict from aqt.qt import * -from aqt.utils import addCloseShortcut, disable_help_button, restoreGeom, saveGeom, tr +from aqt.utils import add_close_shortcut, disable_help_button, restoreGeom, saveGeom, tr class DeckDescriptionDialog(QDialog): @@ -45,7 +45,7 @@ class DeckDescriptionDialog(QDialog): self.setMinimumWidth(400) disable_help_button(self) restoreGeom(self, self.TITLE) - addCloseShortcut(self) + add_close_shortcut(self) box = QVBoxLayout() diff --git a/qt/aqt/deckoptions.py b/qt/aqt/deckoptions.py index 9353da524..cb886a10c 100644 --- a/qt/aqt/deckoptions.py +++ b/qt/aqt/deckoptions.py @@ -13,7 +13,7 @@ from aqt import gui_hooks from aqt.qt import * from aqt.utils import ( KeyboardModifiersPressed, - addCloseShortcut, + add_close_shortcut, disable_help_button, restoreGeom, saveGeom, @@ -42,7 +42,7 @@ class DeckOptionsDialog(QDialog): self.setMinimumWidth(400) disable_help_button(self) restoreGeom(self, self.TITLE, default_size=(800, 800)) - addCloseShortcut(self) + add_close_shortcut(self) self.web = AnkiWebView(kind=AnkiWebViewKind.DECK_OPTIONS) self.web.load_sveltekit_page(f"deck-options/{self._deck['id']}") diff --git a/qt/aqt/editcurrent.py b/qt/aqt/editcurrent.py index f52e1439c..6ec4938b7 100644 --- a/qt/aqt/editcurrent.py +++ b/qt/aqt/editcurrent.py @@ -9,7 +9,7 @@ from anki.collection import OpChanges from anki.errors import NotFoundError from aqt import gui_hooks from aqt.qt import * -from aqt.utils import restoreGeom, saveGeom, tr +from aqt.utils import add_close_shortcut, restoreGeom, saveGeom, tr class EditCurrent(QMainWindow): @@ -36,6 +36,7 @@ class EditCurrent(QMainWindow): close_button = self.form.buttonBox.button(QDialogButtonBox.StandardButton.Close) assert close_button is not None close_button.setShortcut(QKeySequence("Ctrl+Return")) + add_close_shortcut(self) # qt5.14+ doesn't handle numpad enter on Windows self.compat_add_shorcut = QShortcut(QKeySequence("Ctrl+Enter"), self) qconnect(self.compat_add_shorcut.activated, close_button.click) diff --git a/qt/aqt/exporting.py b/qt/aqt/exporting.py index ee41030f7..4ff024917 100644 --- a/qt/aqt/exporting.py +++ b/qt/aqt/exporting.py @@ -19,6 +19,7 @@ from aqt import gui_hooks from aqt.errors import show_exception from aqt.qt import * from aqt.utils import ( + add_close_shortcut, checkInvalidFilename, disable_help_button, getSaveFile, @@ -46,6 +47,7 @@ class ExportDialog(QDialog): self.cids = cids disable_help_button(self) self.setup(did) + add_close_shortcut(self) self.exec() def setup(self, did: DeckId | None) -> None: diff --git a/qt/aqt/fields.py b/qt/aqt/fields.py index 69e38f446..16a3b2779 100644 --- a/qt/aqt/fields.py +++ b/qt/aqt/fields.py @@ -15,6 +15,7 @@ from aqt.qt import * from aqt.schema_change_tracker import ChangeTracker from aqt.utils import ( HelpPage, + add_close_shortcut, askUser, disable_help_button, getOnlyText, @@ -50,6 +51,7 @@ class FieldDialog(QDialog): without_unicode_isolation(tr.fields_fields_for(val=self.model["name"])) ) + add_close_shortcut(self) disable_help_button(self) help_button = self.form.buttonBox.button(QDialogButtonBox.StandardButton.Help) assert help_button is not None diff --git a/qt/aqt/import_export/exporting.py b/qt/aqt/import_export/exporting.py index 4903faea3..c6532ba02 100644 --- a/qt/aqt/import_export/exporting.py +++ b/qt/aqt/import_export/exporting.py @@ -27,6 +27,7 @@ from aqt.operations import QueryOp from aqt.progress import ProgressUpdate from aqt.qt import * from aqt.utils import ( + add_close_shortcut, checkInvalidFilename, disable_help_button, getSaveFile, @@ -53,6 +54,7 @@ class ExportDialog(QDialog): self.nids = nids disable_help_button(self) self.setup(did) + add_close_shortcut(self) self.open() def setup(self, did: DeckId | None) -> None: diff --git a/qt/aqt/import_export/import_dialog.py b/qt/aqt/import_export/import_dialog.py index 68482d39e..0726d64e8 100644 --- a/qt/aqt/import_export/import_dialog.py +++ b/qt/aqt/import_export/import_dialog.py @@ -12,7 +12,7 @@ import aqt.deckconf import aqt.main import aqt.operations from aqt.qt import * -from aqt.utils import addCloseShortcut, disable_help_button, restoreGeom, saveGeom, tr +from aqt.utils import add_close_shortcut, disable_help_button, restoreGeom, saveGeom, tr from aqt.webview import AnkiWebView, AnkiWebViewKind @@ -62,7 +62,7 @@ class ImportDialog(QDialog): self.setMinimumSize(*self.MIN_SIZE) disable_help_button(self) restoreGeom(self, self.args.title, default_size=self.DEFAULT_SIZE) - addCloseShortcut(self) + add_close_shortcut(self) self.web: AnkiWebView | None = AnkiWebView(kind=self.args.kind) self.web.setVisible(False) diff --git a/qt/aqt/operations/scheduling.py b/qt/aqt/operations/scheduling.py index 958448388..399db76b1 100644 --- a/qt/aqt/operations/scheduling.py +++ b/qt/aqt/operations/scheduling.py @@ -24,7 +24,7 @@ from anki.scheduler.v3 import CardAnswer from anki.scheduler.v3 import Scheduler as V3Scheduler from aqt.operations import CollectionOp from aqt.qt import * -from aqt.utils import disable_help_button, getText, tooltip, tr +from aqt.utils import add_close_shortcut, disable_help_button, getText, tooltip, tr def set_due_date_dialog( @@ -104,6 +104,7 @@ def forget_cards( dialog = QDialog(parent) disable_help_button(dialog) + add_close_shortcut(dialog) form = aqt.forms.forget.Ui_Dialog() form.setupUi(dialog) @@ -153,6 +154,7 @@ def reposition_new_cards_dialog( dialog = QDialog(parent) disable_help_button(dialog) + add_close_shortcut(dialog) dialog.setWindowModality(Qt.WindowModality.WindowModal) form = aqt.forms.reposition.Ui_Dialog() form.setupUi(dialog) diff --git a/qt/aqt/preferences.py b/qt/aqt/preferences.py index 7befe4ca2..37483427a 100644 --- a/qt/aqt/preferences.py +++ b/qt/aqt/preferences.py @@ -22,6 +22,7 @@ from aqt.sync import sync_login from aqt.theme import Theme from aqt.utils import ( HelpPage, + add_close_shortcut, askUser, disable_help_button, is_win, @@ -64,6 +65,7 @@ class Preferences(QDialog): self.setup_profile() self.setup_global() self.setup_configurable_answer_keys() + add_close_shortcut(self) self.show() def setup_configurable_answer_keys(self): diff --git a/qt/aqt/stats.py b/qt/aqt/stats.py index 56fb7ccfd..0b8a8a3ee 100644 --- a/qt/aqt/stats.py +++ b/qt/aqt/stats.py @@ -16,7 +16,7 @@ from aqt.operations.deck import set_current_deck from aqt.qt import * from aqt.theme import theme_manager from aqt.utils import ( - addCloseShortcut, + add_close_shortcut, disable_help_button, getSaveFile, maybeHideClose, @@ -69,7 +69,7 @@ class NewDeckStats(QDialog): assert b is not None b.setAutoDefault(False) maybeHideClose(self.form.buttonBox) - addCloseShortcut(self) + add_close_shortcut(self) gui_hooks.stats_dialog_will_show(self) self.form.web.hide_while_preserving_layout() self.show() @@ -182,7 +182,7 @@ class DeckStats(QDialog): qconnect(f.year.clicked, lambda: self.changePeriod(1)) qconnect(f.life.clicked, lambda: self.changePeriod(2)) maybeHideClose(self.form.buttonBox) - addCloseShortcut(self) + add_close_shortcut(self) gui_hooks.stats_dialog_old_will_show(self) self.show() self.refresh() diff --git a/qt/aqt/studydeck.py b/qt/aqt/studydeck.py index d1c0a5c47..58d205c18 100644 --- a/qt/aqt/studydeck.py +++ b/qt/aqt/studydeck.py @@ -16,6 +16,7 @@ from aqt.qt import * from aqt.utils import ( HelpPage, HelpPageArgument, + add_close_shortcut, disable_help_button, openHelp, restoreGeom, @@ -52,6 +53,7 @@ class StudyDeck(QDialog): gui_hooks.state_did_reset.append(self.onReset) self.geomKey = f"studyDeck-{geomKey}" restoreGeom(self, self.geomKey) + add_close_shortcut(self) disable_help_button(self) if not cancel: self.form.buttonBox.removeButton( diff --git a/qt/aqt/sync.py b/qt/aqt/sync.py index d044a70d4..5a4d5fd4c 100644 --- a/qt/aqt/sync.py +++ b/qt/aqt/sync.py @@ -28,6 +28,7 @@ from aqt.qt import ( qconnect, ) from aqt.utils import ( + add_close_shortcut, ask_user_dialog, disable_help_button, show_warning, @@ -380,6 +381,7 @@ def get_id_and_pass_from_user( qconnect(bb.accepted, diag.accept) qconnect(bb.rejected, diag.reject) vbox.addWidget(bb) + add_close_shortcut(diag) diag.setLayout(vbox) diag.adjustSize() diag.show() diff --git a/qt/aqt/utils.py b/qt/aqt/utils.py index 19fd06b03..db45a10e9 100644 --- a/qt/aqt/utils.py +++ b/qt/aqt/utils.py @@ -560,6 +560,7 @@ def getText( d = GetTextDialog( parent, prompt, help=help, edit=edit, default=default, title=title, **kwargs ) + add_close_shortcut(d) d.setWindowModality(Qt.WindowModality.WindowModal) if geomKey: restoreGeom(d, geomKey) @@ -988,14 +989,6 @@ def maybeHideClose(bbox: QDialogButtonBox) -> None: bbox.removeButton(b) -def addCloseShortcut(widg: QDialog) -> None: - if not is_mac: - return - shortcut = QShortcut(QKeySequence("Ctrl+W"), widg) - qconnect(shortcut.activated, widg.reject) - setattr(widg, "_closeShortcut", shortcut) - - def add_close_shortcut(widg: QWidget) -> None: if not is_mac: return