summaryrefslogtreecommitdiff
path: root/.local/share/Anki2/addons21/keybindings/custom_shortcuts.py
diff options
context:
space:
mode:
authorThanosApollo <[email protected]>2022-09-01 07:41:39 +0300
committerThanosApollo <[email protected]>2022-09-01 07:41:39 +0300
commit0c89df9be987008e55c1b336489c41290653434b (patch)
tree73425d852d363acdd6c9297a97616b23f9311bd4 /.local/share/Anki2/addons21/keybindings/custom_shortcuts.py
parenta6d1ec012952c5e955676af22732cd177d1f3abf (diff)
Remove anki addons
Diffstat (limited to '.local/share/Anki2/addons21/keybindings/custom_shortcuts.py')
-rw-r--r--.local/share/Anki2/addons21/keybindings/custom_shortcuts.py882
1 files changed, 0 insertions, 882 deletions
diff --git a/.local/share/Anki2/addons21/keybindings/custom_shortcuts.py b/.local/share/Anki2/addons21/keybindings/custom_shortcuts.py
deleted file mode 100644
index c0209a6..0000000
--- a/.local/share/Anki2/addons21/keybindings/custom_shortcuts.py
+++ /dev/null
@@ -1,882 +0,0 @@
-# Last updated to be useful for: Anki 2.1.45
-import warnings
-from anki.lang import _
-from aqt import mw
-from aqt.qt import *
-from anki.hooks import runHook,addHook,wrap
-try:
- from aqt.utils import (
- TR,
- shortcut,
- showWarning,
- tr,
- )
- tr_import = True
-except:
- from aqt.utils import showWarning
- tr_import = False
-from aqt.toolbar import Toolbar
-from aqt.editor import Editor, EditorWebView
-try:
- from aqt.editor import EditorMode
- editor_mode_import = True
-except:
- editor_mode_import = False
-from aqt.reviewer import Reviewer
-from aqt.browser import Browser
-from aqt.modelchooser import ModelChooser
-
-try:
- from aqt.notetypechooser import NotetypeChooser
- notetypechooser_import = True
-except:
- notetypechooser_import = False
-from aqt.addcards import AddCards
-from anki.utils import json
-from bs4 import BeautifulSoup
-from . import cs_functions as functions
-try:
- from aqt.operations.notetype import update_notetype_legacy
-except:
- pass
-
-# Anki before version 2.1.20 does not use aqt.gui_hooks
-try:
- from aqt import gui_hooks
- new_hooks = True
-except:
- new_hooks = False
-
-# Gets config.json as config
-config = mw.addonManager.getConfig(__name__)
-CS_CONFLICTSTR = "Custom Shortcut Conflicts: \n\n"
-# config_scuts initialized after cs_traverseKeys
-Qt_functions = {"Qt.Key_Enter": Qt.Key_Enter,
- "Qt.Key_Return": Qt.Key_Return,
- "Qt.Key_Escape": Qt.Key_Escape,
- "Qt.Key_Space": Qt.Key_Space,
- "Qt.Key_Tab": Qt.Key_Tab,
- "Qt.Key_Backspace": Qt.Key_Backspace,
- "Qt.Key_Delete": Qt.Key_Delete,
- "Qt.Key_Left": Qt.Key_Left,
- "Qt.Key_Down": Qt.Key_Down,
- "Qt.Key_Right": Qt.Key_Right,
- "Qt.Key_Up": Qt.Key_Up,
- "Qt.Key_PageUp": Qt.Key_PageUp,
- "Qt.Key_PageDown": Qt.Key_PageDown,
- "<nop>": ""
- }
-
-# There is a weird interaction with QShortcuts wherein if there are 2 (or more)
-# QShortcuts mapped to the same key and function and both are enabled,
-# the shortcut doesn't work
-
-# There isn't an obvious way to get the original QShortcut objects, as
-# The addons executes after the setup phase (which creates QShortcut objects)
-
-def cs_traverseKeys(Rep, D):
- ret = {}
- for key in D:
- if isinstance(D[key],dict):
- ret[key] = cs_traverseKeys(Rep,D[key])
- elif D[key] in Rep:
- ret[key] = Rep[D[key]]
- else:
- ret[key] = D[key]
- return ret
-
-
-# Since QShortcuts cannot reveal their action (to the best of my knowledge),
-# This map reconstructs what each QShortcut is supposed to do from its id
-# The ids were found manually but so far have remained constant
-mainShortcutIds = {-1: "main debug",
- -2: "main deckbrowser",
- -3: "main study",
- -4: "main add",
- -5: "main browse",
- -6: "main stats",
- -7: "main sync"
- }
-
-# This contains the processed shortcuts used for the rest of the functions
-config_scuts = cs_traverseKeys(Qt_functions,config)
-
-# The main shortcuts are now found by manually going through all QT shortcuts
-# and replacing them with their custom shortcut equivalent
-
-mainShortcutPairs = {
- "Ctrl+:": config_scuts["main debug"],
- "D": config_scuts["main deckbrowser"],
- "S": config_scuts["main study"],
- "A": config_scuts["main add"],
- "B": config_scuts["main browse"],
- "T": config_scuts["main stats"],
- "Y": config_scuts["main sync"],
- }
-
-# Finds all the shortcuts, figures out relevant ones from hardcoded shortcut check,
-# and sets it to the right one
-# This function has a side effect of changing the shortcut's id
-def cs_main_setupShortcuts():
- mwShortcuts = mw.findChildren(QShortcut)
- if functions.get_version() >= 50:
- for child in mwShortcuts:
- if child.key().toString() in mainShortcutPairs:
- oldScut = child.key().toString()
- newScut = mainShortcutPairs[oldScut]
- child.setKey(newScut)
- mainShortcutPairs.pop(oldScut) # Only replace shortcuts once (the first time would be the main shortcut)
- else: # If possible, use the old shortcut remapping method
- # This may be removed if the new method is fount to be more stable
- for scut in mwShortcuts:
- if scut.id() in mainShortcutIds:
- scut.setKey(config_scuts[mainShortcutIds[scut.id()]])
-
-
-# Governs the shortcuts on the main toolbar
-def cs_mt_setupShortcuts():
- m = mw.form
- # Goes through and includes anything on the duplicates list
- scuts_list = {
- "m_toolbox quit": [config_scuts["m_toolbox quit"]],
- "m_toolbox preferences": [config_scuts["m_toolbox preferences"]],
- "m_toolbox undo": [config_scuts["m_toolbox undo"]],
- "m_toolbox see documentation": [config_scuts["m_toolbox see documentation"]],
- "m_toolbox switch profile": [config_scuts["m_toolbox switch profile"]],
- "m_toolbox export": [config_scuts["m_toolbox export"]],
- "m_toolbox import": [config_scuts["m_toolbox import"]],
- "m_toolbox study": [config_scuts["m_toolbox study"]],
- "m_toolbox create filtered deck": [config_scuts["m_toolbox create filtered deck"]],
- "m_toolbox addons": [config_scuts["m_toolbox addons"]]
- }
- for act, key in config_scuts["m_toolbox _duplicates"].items():
- scuts_list[functions.normalizeShortcutName(act)].append(key)
- m.actionExit.setShortcuts(scuts_list["m_toolbox quit"])
- m.actionPreferences.setShortcuts(scuts_list["m_toolbox preferences"])
- m.actionUndo.setShortcuts(scuts_list["m_toolbox undo"])
- m.actionDocumentation.setShortcuts(scuts_list["m_toolbox see documentation"])
- m.actionSwitchProfile.setShortcuts(scuts_list["m_toolbox switch profile"])
- m.actionExport.setShortcuts(scuts_list["m_toolbox export"])
- m.actionImport.setShortcuts(scuts_list["m_toolbox import"])
- m.actionStudyDeck.setShortcuts(scuts_list["m_toolbox study"])
- m.actionCreateFiltered.setShortcuts(scuts_list["m_toolbox create filtered deck"])
- m.actionAdd_ons.setShortcuts(scuts_list["m_toolbox addons"])
-
-# Governs the shortcuts on the review window
-# This replacement method is pretty blind but tries to minimize disruption
-# Replaces shortcuts at the start first
-# If other addons append shortcuts, this shouldn't bother those addons
-def cs_review_setupShortcuts(self, _old):
- # More fragile replacement: For these shortcuts,
- # Their functions are lambdas, so we can't directly address them
- # I'm not completely satisfied by this option
- new_scut_replacements = {
- "Ctrl+1" : config_scuts["reviewer set flag 1"],
- "Ctrl+2" : config_scuts["reviewer set flag 2"],
- "Ctrl+3" : config_scuts["reviewer set flag 3"],
- "Ctrl+4" : config_scuts["reviewer set flag 4"],
- "1" : config_scuts["reviewer choice 1"],
- "2" : config_scuts["reviewer choice 2"],
- "3" : config_scuts["reviewer choice 3"],
- "4" : config_scuts["reviewer choice 4"],
- }
- if functions.get_version() >= 45:
- new_scut_replacements["Ctrl+5"] = config_scuts["reviewer set flag 5"]
- new_scut_replacements["Ctrl+6"] = config_scuts["reviewer set flag 6"]
- new_scut_replacements["Ctrl+7"] = config_scuts["reviewer set flag 7"]
-
- # Less fragile replacement: For these shortcuts, address them by pointer and replace shortcut
- # The keys are dicts because we will want to replace multiply shortcut keys
- new_function_replacements = {
- self.mw.onEditCurrent : [config_scuts["reviewer edit current"]],
- self.onEnterKey : [
- config_scuts["reviewer flip card 1"],
- config_scuts["reviewer flip card 2"],
- config_scuts["reviewer flip card 3"]],
- self.replayAudio : [
- config_scuts["reviewer replay audio 1"],
- config_scuts["reviewer replay audio 2"],
- ],
- self.onMark : [config_scuts["reviewer mark card"]],
- self.onBuryNote : [config_scuts["reviewer bury note"]],
- self.onBuryCard : [config_scuts["reviewer bury card"]],
- self.onSuspend : [config_scuts["reviewer suspend note"]],
- self.onSuspendCard : [config_scuts["reviewer suspend card"]],
- self.onDelete : [config_scuts["reviewer delete note"]],
- self.onReplayRecorded : [config_scuts["reviewer play recorded voice"]],
- self.onRecordVoice : [config_scuts["reviewer record voice"]],
- self.onOptions : [config_scuts["reviewer options menu"]],
- }
- cuts = _old(self)
- # Order is important: shortcut-based replacement should come first
- functions.reviewer_find_and_replace_scuts(cuts,new_scut_replacements)
-
- if functions.get_version() >= 20:
- new_function_replacements[self.on_pause_audio] = [config_scuts["reviewer pause audio"]]
- new_function_replacements[self.on_seek_backward] = [config_scuts["reviewer seek backward"]]
- new_function_replacements[self.on_seek_forward] = [config_scuts["reviewer seek forward"]]
- if functions.get_version() >= 33:
- new_function_replacements[self.showContextMenu] = [config_scuts["reviewer more options"]]
- if functions.get_version() >= 41:
- new_function_replacements[self.on_set_due] = [config_scuts["reviewer set due date"]]
- if functions.get_version() >= 45:
- new_function_replacements[self.on_card_info] = [config_scuts["reviewer card info"]]
- if functions.get_version() >= 48:
- new_function_replacements[self.on_previous_card_info] = [config_scuts["reviewer previous card info"]]
- functions.reviewer_find_and_replace_functions(cuts,new_function_replacements)
- for scut in config_scuts["reviewer _duplicates"]:
- cuts.append((config_scuts["reviewer _duplicates"][scut], self.sToF(scut)))
- return cuts
-
-# The function to setup shortcuts on the Editor
-# Something funky is going on with the default MathJax and LaTeX shortcuts
-# It does not affect the function (as I currently know of)
-def cs_editor_setupShortcuts(self):
- dupes = []
- # if a third element is provided, enable shortcut even when no field is selected
- cuts = [
- (config_scuts["editor card layout"], self.onCardLayout, True),
- (config_scuts["editor bold"], self.toggleBold),
- (config_scuts["editor italic"], self.toggleItalic),
- (config_scuts["editor underline"], self.toggleUnderline),
- (config_scuts["editor superscript"], self.toggleSuper),
- (config_scuts["editor subscript"], self.toggleSub),
- (config_scuts["editor remove format"], self.removeFormat),
- (config_scuts["editor cloze"], self.onCloze),
- (config_scuts["editor cloze alt"], self.onCloze),
- (config_scuts["editor cloze forced increment"], self.cs_onStdCloze),
- (config_scuts["editor cloze no increment"], self.cs_onAltCloze),
- (config_scuts["editor add media"], self.onAddMedia),
- (config_scuts["editor record sound"], self.onRecSound),
- (config_scuts["editor insert latex"], self.insertLatex),
- (config_scuts["editor insert latex equation"], self.insertLatexEqn),
- (config_scuts["editor insert latex math environment"], self.insertLatexMathEnv),
- (config_scuts["editor insert mathjax inline"], self.insertMathjaxInline),
- (config_scuts["editor insert mathjax block"], self.insertMathjaxBlock),
- (config_scuts["editor focus tags"], self.onFocusTags, True),
- (config_scuts["editor _extras"]["paste custom text"],
- lambda text=config_scuts["Ω custom paste text"]: self.customPaste(text)),
- ]
- # Due to the svelte changes, these shortcuts "break"
- # in the sense that they no longer correspond to the most recent shortcuts
- cuts += [(config_scuts["editor foreground"], self.onForeground),
- (config_scuts["editor change col"], self.onChangeCol),
- ]
- if functions.get_version() >= 45:
- if functions.get_version() >= 50:
- pass
- else:
- cuts += [
- (config_scuts["editor html edit"], lambda:
- self.web.eval(
- """{const currentField = getCurrentField(); if (currentField) { currentField.toggleHtmlEdit(); }}"""
- )),
- ]
- cuts += [
- (config_scuts["editor toggle sticky current"], self.csToggleStickyCurrent),
- (config_scuts["editor toggle sticky all"], self.csToggleStickyAll),
- (config_scuts["editor block indent"], lambda:
- self.web.eval(
- """
- {
- document.execCommand("indent");
- }
- """
- )
- ),
- (config_scuts["editor block outdent"], lambda:
- self.web.eval(
- """
- {
- document.execCommand("outdent")
- }
- """
- )
- ),
- (config_scuts["editor list insert unordered"], lambda:
- self.web.eval(
- """
- document.execCommand("insertUnorderedList");
- """
- )
- ),
- (config_scuts["editor list insert ordered"], lambda:
- self.web.eval(
- """
- document.execCommand("insertOrderedList");
- """
- )
- ),
- ]
- else:
- cuts += [
- (config_scuts["editor html edit"], self.onHtmlEdit),]
-
- for scut in config_scuts["editor _duplicates"]:
- if self.sToF(scut):
- dupes.append((config_scuts["editor _duplicates"][scut],)+self.sToF(scut))
- cuts += dupes
- for label in config_scuts["editor _pastes"]:
- if label in config_scuts["Ω custom paste extra texts"]:
- scut = config_scuts["editor _pastes"][label]
- temp = config_scuts["Ω custom paste extra texts"][label]
- cuts.append((scut, lambda text=temp: self.customPaste(text)))
- # There is a try-except clause to handle 2.1.0 version, which does not have this shortcut
- try:
- cuts.append((config_scuts["editor insert mathjax chemistry"], self.insertMathjaxChemistry))
- except AttributeError:
- pass
- if new_hooks:
- gui_hooks.editor_did_init_shortcuts(cuts, self)
- else:
- runHook("setupEditorShortcuts", cuts, self)
- for row in cuts:
- if len(row) == 2:
- keys, fn = row
- fn = self._addFocusCheck(fn)
- else:
- keys, fn, _ = row
- scut = QShortcut(QKeySequence(keys), self.widget, activated=fn)
-
-# Wrapper function to add another shortcut to change note type
-# Not with the other custom shortcut editor functions because
-# the Anki functionality handling card type is not
-# in the Editor itself
-def cs_editorChangeNoteType(self):
- NOTE_TYPE_STR = "editor change note type"
- new_scuts = {config_scuts[NOTE_TYPE_STR]}
- for act, key in config_scuts["editor _duplicates"].items():
- if functions.normalizeShortcutName(act) == NOTE_TYPE_STR:
- new_scuts.add(key)
- for scut in new_scuts:
- if functions.get_version() >= 41:
- QShortcut(QKeySequence(scut), self._widget, activated=self.on_activated)
- elif functions.get_version() >= 36:
- QShortcut(QKeySequence(scut), self.widget, activated=self.on_activated)
- else:
- QShortcut(QKeySequence(scut), self.widget, activated=self.onModelChange)
-
-def cs_editorNotetypeChooser(self, show_label: bool):
- NOTE_TYPE_STR = "editor change note type"
- new_scuts = {config_scuts[NOTE_TYPE_STR]}
- for act, key in config_scuts["editor _duplicates"].items():
- if functions.normalizeShortcutName(act) == NOTE_TYPE_STR:
- new_scuts.add(key)
- for scut in new_scuts:
- # Since the hard-coded shortcut for this is Ctrl+N,
- # Don't destroy the existing shortcut
- # (has the side effect of leaving Ctrl+N assigned at all times)
- if scut == "Ctrl+N":
- continue
- qconnect(QShortcut(QKeySequence(scut), self._widget).activated,
- self.on_button_activated
- )
-
-def cs_editorUpdateStickyPins(self, stickies, model):
- stickiesStr = ""
-
- # Hack: the svelte interface exposes a function "setSticky" which manually sets the sticky displays of all the pins
- # Manually create a set of stickies in order to set the sticky pins to the right display value
- stickiesStr += "["
- firstInput = True
- for sticky in stickies:
- if not firstInput:
- stickiesStr += ","
- firstInput = False
- stickiesStr += ("true" if sticky else "false")
- stickiesStr += "]"
-
- try:
- update_notetype_legacy(parent=self.mw, notetype=model).run_in_background(
- initiator=self
- )
- self.web.eval("setSticky({})".format(stickiesStr))
- except:
- pass
-
-def cs_editorToggleSticky(self, index: int):
- model = self.note.note_type()
- flds = model["flds"]
- stickies = []
- flds[index]["sticky"] = not flds[index]["sticky"]
- for fld in flds:
- stickies.append(fld["sticky"])
- cs_editorUpdateStickyPins(self, stickies, model)
-
-
-# Toggle sticky on all fields
-# "Toggle" is interpreted as it is in Anki:
-# If any sticky is on, turn everything off
-# If all stickies are off, turn everything on
-def cs_editorToggleStickyAll(self):
- model = self.note.note_type()
- flds = model["flds"]
-
- any_sticky = any([fld["sticky"] for fld in flds])
- stickies = []
- for fld in flds:
- if not any_sticky or fld["sticky"]:
- fld["sticky"] = not fld["sticky"]
- stickies.append(fld["sticky"])
- cs_editorUpdateStickyPins(self, stickies, model)
-
-# Toggle sticky on the current field
-def cs_editorToggleStickyCurrent(self):
- if self.currentField is not None:
- cs_editorToggleSticky(self,self.currentField)
-
-# Intercepts the bridge functions normally used to toggle stickiness
-def cs_captureBridgeToggleSticky(self, cmd, _old):
- # If we intercept a "toggle sticky all" command, then
- if cmd.startswith("toggleStickyAll") and config_scuts["editor toggle sticky all"] != "Shift+F9":
- model = self.note.note_type()
- return model["flds"]["sticky"]
- elif cmd.startswith("toggleSticky") and config_scuts["editor toggle sticky current"] != "F9":
- model = self.note.note_type()
- (_, num) = cmd.split(":",1)
- idx = int(num)
-
- return model["flds"][idx]["sticky"]
- return _old(self,cmd)
-
-
-# Wrapper function to change the shortcut to add a card
-# Not with the other custom shortcut editor functions because
-# the add card button is not within the Editor class
-def cs_editorAddCard(self):
- ADD_CARD_STR = "editor confirm add card"
- self.addButton.setShortcut(QKeySequence(config_scuts[ADD_CARD_STR]))
- for act, key in config_scuts["editor _duplicates"].items():
- if functions.normalizeShortcutName(act) == ADD_CARD_STR:
- QShortcut(QKeySequence(key), self, activated=self.addCards)
-
-def cs_editorChangeDeck(self):
- CHANGE_DECK_STR = "editor change deck"
- new_scuts = {config_scuts[CHANGE_DECK_STR]}
- for act, key in config_scuts["editor _duplicates"].items():
- if functions.normalizeShortcutName(act) == CHANGE_DECK_STR:
- new_scuts.add(key)
- for scut in new_scuts:
- QShortcut(QKeySequence(scut), self.widget, activated=self.cs_changeDeck)
-
-# IMPLEMENTS Browser shortcuts
-def cs_browser_setupShortcuts(self):
- f = self.form
- try:
- f.previewButton.setShortcut(config_scuts["window_browser preview"])
- except:
- pass
- try:
- f.action_set_due_date.setShortcut(config_scuts["window_browser reschedule"])
- except:
- f.actionReschedule.setShortcut(config_scuts["window_browser reschedule"])
- f.actionSelectAll.setShortcut(config_scuts["window_browser select all"])
- f.actionUndo.setShortcut(config_scuts["window_browser undo"])
- f.actionInvertSelection.setShortcut(config_scuts["window_browser invert selection"])
- f.actionFind.setShortcut(config_scuts["window_browser find"])
- f.actionNote.setShortcut(config_scuts["window_browser goto note"])
- f.actionNextCard.setShortcut(config_scuts["window_browser goto next note"])
- f.actionPreviousCard.setShortcut(config_scuts["window_browser goto previous note"])
- f.actionChangeModel.setShortcut(config_scuts["window_browser change note type"])
- f.actionGuide.setShortcut(config_scuts["window_browser guide"])
- f.actionFindReplace.setShortcut(config_scuts["window_browser find and replace"])
- try:
- f.actionTags.setShortcut(config_scuts["window_browser filter"])
- except AttributeError:
- f.actionSidebarFilter.setShortcut(config_scuts["window_browser filter"])
- f.actionCardList.setShortcut(config_scuts["window_browser goto card list"])
- f.actionReposition.setShortcut(config_scuts["window_browser reposition"])
- f.actionFirstCard.setShortcut(config_scuts["window_browser first card"])
- f.actionLastCard.setShortcut(config_scuts["window_browser last card"])
- f.actionClose.setShortcut(config_scuts["window_browser close"])
- f.action_Info.setShortcut(config_scuts["window_browser info"])
- f.actionAdd_Tags.setShortcut(config_scuts["window_browser add tag"])
- f.actionRemove_Tags.setShortcut(config_scuts["window_browser remove tag"])
- f.actionToggle_Suspend.setShortcut(config_scuts["window_browser suspend"])
- f.actionDelete.setShortcut(config_scuts["window_browser delete"])
- f.actionAdd.setShortcut(config_scuts["window_browser add note"])
- f.actionChange_Deck.setShortcut(config_scuts["window_browser change deck"])
- f.actionRed_Flag.setShortcut(config_scuts["window_browser flag_red"])
- try:
- f.actionOrange_Flag.setShortcut(config_scuts["window_browser flag_orange"])
- except AttributeError:
- f.actionPurple_Flag.setShortcut(config_scuts["window_browser flag_orange"])
- f.actionGreen_Flag.setShortcut(config_scuts["window_browser flag_green"])
- f.actionBlue_Flag.setShortcut(config_scuts["window_browser flag_blue"])
- f.actionSidebar.setShortcut(config_scuts["window_browser goto sidebar"])
- f.actionToggle_Mark.setShortcut(config_scuts["window_browser toggle mark"])
- f.actionClear_Unused_Tags.setShortcut(config_scuts["window_browser clear unused tags"])
- f.actionFindDuplicates.setShortcut(config_scuts["window_browser find duplicates"])
- f.actionSelectNotes.setShortcut(config_scuts["window_browser select notes"])
- f.actionManage_Note_Types.setShortcut(config_scuts["window_browser manage note types"])
- try:
- f.action_forget.setShortcut(config_scuts["window_browser forget card"])
- except AttributeError:
- pass
-
-# Mimics the style of other Anki functions, analogue of customPaste
-# Note that the saveNow function used earler takes the cursor to the end of the line,
-# as it is meant to save work before entering a new window
-def cs_editor_custom_paste(self, text):
- self._customPaste(text)
-
-# Mimics the style of other Anki functions, analogue of _customPaste
-def cs_uEditor_custom_paste(self, text):
- html = text
- if config_scuts["Ω custom paste end style"].upper() == "Y":
- html += "</span>\u200b"
- with warnings.catch_warnings() as w:
- warnings.simplefilter('ignore', UserWarning)
- html = str(BeautifulSoup(html, "html.parser"))
- self.doPaste(html,True,True)
-
-# detects shortcut conflicts
-# Gets all the shortcuts in a given object of the form {name: scut, ...} and names them
-# Returns a dictionary of the form {scut: [labels of objects with that scut], ...}
-def cs_getAllScuts(obj, strCont):
- res = {}
- for key in obj:
- if isinstance(obj[key], dict):
- rec = cs_getAllScuts(obj[key], key + " in " + strCont)
- for term in rec:
- if term in res:
- res[term] += rec[term]
- else:
- res[term] = rec[term]
- else:
- text_scut = obj[key].upper()
- if text_scut in res:
- res[text_scut].append(key + " in " + strCont)
- else:
- res[text_scut] = [key + " in " + strCont]
- return res
-
-# Ignores the Add-on (Ω) options
-def cs_conflictDetect():
- if config["Ω enable conflict warning"].upper() != "Y":
- return
- ext_list = {}
- for e in config:
- sub = e[0:(e.find(" "))]
- val = config[e]
- if sub == "Ω":
- continue
- if sub not in ext_list:
- ext_list[sub] = {}
- if isinstance(val, dict):
- scuts = cs_getAllScuts(val, e)
- for scut in scuts:
- if scut in ext_list[sub]:
- ext_list[sub][scut] += scuts[scut]
- else:
- ext_list[sub][scut] = scuts[scut]
- else:
- text_val = val.upper()
- if text_val in ext_list[sub]:
- ext_list[sub][text_val].append(e)
- else:
- ext_list[sub][text_val] = [e]
- conflictStr = CS_CONFLICTSTR
- conflict = False
- for key in ext_list:
- for k in ext_list[key]:
- if len(ext_list[key][k]) == 1:
- continue
- if k == "<NOP>":
- continue
- if not k:
- continue
- conflict = True
- conflictStr += ", ".join(ext_list[key][k])
- conflictStr += "\nshare '" + k + "' as a shortcut\n\n"
- if conflict:
- conflictStr += "\nThese shortcuts will not work.\n"
- conflictStr += "Please change them in the config.json."
- showWarning(conflictStr)
-
-def cs_toolbarCenterLinks(self):
- try:
- links = [
- self.create_link(
- "decks",
- tr(TR.ACTIONS_DECKS),
- self._deckLinkHandler,
- tip=tr(TR.ACTIONS_SHORTCUT_KEY, val=config_scuts["main deckbrowser"]),
- id="decks",
- ),
- self.create_link(
- "add",
- tr(TR.ACTIONS_ADD),
- self._addLinkHandler,
- tip=tr(TR.ACTIONS_SHORTCUT_KEY, val=config_scuts["main add"]),
- id="add",
- ),
- self.create_link(
- "browse",
- tr(TR.QT_MISC_BROWSE),
- self._browseLinkHandler,
- tip=tr(TR.ACTIONS_SHORTCUT_KEY, val=config_scuts["main browse"]),
- id="browse",
- ),
- self.create_link(
- "stats",
- tr(TR.QT_MISC_STATS),
- self._statsLinkHandler,
- tip=tr(TR.ACTIONS_SHORTCUT_KEY, val=config_scuts["main stats"]),
- id="stats",
- ),
- ]
-
- links.append(self._create_sync_link())
-
- gui_hooks.top_toolbar_did_init_links(links, self)
-
- return "\n".join(links)
- except:
- pass
- try:
- links = [
- self.create_link(
- "decks",
- _("Decks"),
- self._deckLinkHandler,
- tip=_("Shortcut key: %s") % config_scuts["main deckbrowser"],
- id="decks",
- ),
- self.create_link(
- "add",
- _("Add"),
- self._addLinkHandler,
- tip=_("Shortcut key: %s") % config_scuts["main add"],
- id="add",
- ),
- self.create_link(
- "browse",
- _("Browse"),
- self._browseLinkHandler,
- tip=_("Shortcut key: %s") % config_scuts["main browse"],
- id="browse",
- ),
- self.create_link(
- "stats",
- _("Stats"),
- self._statsLinkHandler,
- tip=_("Shortcut key: %s") % config_scuts["main stats"],
- id="stats",
- ),
- ]
-
- links.append(self._create_sync_link())
-
- gui_hooks.top_toolbar_did_init_links(links, self)
-
- return "\n".join(links)
- except:
- links = [
- ["decks", _("Decks"), _("Shortcut key: %s") % config_scuts["main deckbrowser"]],
- ["add", _("Add"), _("Shortcut key: %s") % config_scuts["main add"]],
- ["browse", _("Browse"), _("Shortcut key: %s") % config_scuts["main browse"]],
- ["stats", _("Stats"), _("Shortcut key: %s") % config_scuts["main stats"]],
- ["sync", _("Sync"), _("Shortcut key: %s") % config_scuts["main sync"]],
- ]
- return self._linkHTML(links)
-
-def cs_browser_basicFilter(self, txt):
- self.form.searchEdit.lineEdit().setText(txt)
- self.onSearchActivated()
-
-def cs_browser_concatFilter(self, txt):
- cur = str(self.form.searchEdit.lineEdit().text())
- if cur and cur != self._searchPrompt:
- txt = cur + " " + txt
- self.form.searchEdit.lineEdit().setText(txt)
- self.onSearchActivated()
-
-def cs_browser_orConcatFilter(self, txt):
- cur = str(self.form.searchEdit.lineEdit().text())
- if cur:
- txt = cur + " or " + txt
- self.form.searchEdit.lineEdit().setText(txt)
- self.onSearchActivated()
-
-# Inserts the custom filter shortcuts upon browser startup
-def cs_browser_setupEditor(self):
- if functions.get_version() >= 50 and editor_mode_import:
- QShortcut(QKeySequence(config_scuts["window_browser preview"]), self, self.onTogglePreview)
- def add_preview_button(editor):
- editor._links["preview"] = lambda _editor: self.onTogglePreview()
- gui_hooks.editor_did_init.append(add_preview_button)
- self.editor = Editor(self.mw, self.form.fieldsArea, self, editor_mode=EditorMode.BROWSER,)
- gui_hooks.editor_did_init.remove(add_preview_button)
- elif functions.get_version() >= 45:
- QShortcut(QKeySequence(config_scuts["window_browser preview"]), self, self.onTogglePreview)
- def add_preview_button(editor):
- preview_shortcut = config_scuts["window_browser preview"]
-
- editor._links["preview"] = lambda _editor: self.onTogglePreview()
- editor.web.eval(
- "$editorToolbar.then(({ notetypeButtons }) => notetypeButtons.appendButton({ component: editorToolbar.PreviewButton, id: 'preview' }));"
- )
- gui_hooks.editor_did_init.append(add_preview_button)
- self.editor = Editor(self.mw, self.form.fieldsArea, self)
- gui_hooks.editor_did_init.remove(add_preview_button)
- elif functions.get_version() >= 39:
- def add_preview_button(leftbuttons, editor):
- preview_shortcut = config_scuts["window_browser preview"]
- leftbuttons.insert(
- 0,
- editor.addButton(
- None,
- "preview",
- lambda _editor: self.onTogglePreview(),
- tr(
- TR.BROWSING_PREVIEW_SELECTED_CARD,
- val=shortcut(preview_shortcut),
- ),
- tr(TR.ACTIONS_PREVIEW),
- id="previewButton",
- keys=preview_shortcut,
- disables=False,
- rightside=False,
- toggleable=True,
- ),
- )
- gui_hooks.editor_did_init_left_buttons.append(add_preview_button)
- self.editor = Editor(self.mw, self.form.fieldsArea, self)
- gui_hooks.editor_did_init_left_buttons.remove(add_preview_button)
- else:
- self.editor = Editor(self.mw, self.form.fieldsArea, self)
- self.csFilterScuts = {}
- self.csFilterFuncs = {}
- self.csCatFilterScuts = {}
- self.csCatFilterFuncs = {}
- self.csOCatFilterScuts = {}
- self.csOCatFilterFuncs = {}
- for filt in config_scuts["window_browser _filters"]:
- scut = config_scuts["window_browser _filters"][filt]
- if isinstance(scut, dict):
- continue
- self.csFilterFuncs[filt] = lambda txt=filt: cs_browser_basicFilter(self, txt)
- self.csFilterScuts[filt] = QShortcut(QKeySequence(scut), self)
- self.csFilterScuts[filt].activated.connect(self.csFilterFuncs[filt])
- if "_concat" in config_scuts["window_browser _filters"]:
- for filt in config_scuts["window_browser _filters"]["_concat"]:
- scut = config_scuts["window_browser _filters"]["_concat"][filt]
- self.csCatFilterFuncs[filt] = lambda txt=filt: cs_browser_concatFilter(self, txt)
- self.csCatFilterScuts[filt] = QShortcut(QKeySequence(scut), self)
- self.csCatFilterScuts[filt].activated.connect(self.csCatFilterFuncs[filt])
- if "_orConcat" in config_scuts["window_browser _filters"]:
- for filt in config_scuts["window_browser _filters"]["_orConcat"]:
- scut = config_scuts["window_browser _filters"]["_orConcat"][filt]
- self.csOCatFilterFuncs[filt] = lambda txt=filt: cs_browser_orConcatFilter(self, txt)
- self.csOCatFilterScuts[filt] = QShortcut(QKeySequence(scut), self)
- self.csOCatFilterScuts[filt].activated.connect(self.csOCatFilterFuncs[filt])
- if config_scuts["window_browser save current filter"]:
- self.csSaveFilterScut = QShortcut(QKeySequence(config_scuts["window_browser save current filter"]), self)
- self.csSaveFilterScut.activated.connect(self._onSaveFilter)
- if config_scuts["window_browser remove current filter"]:
- self.csRemoveFilterScut = QShortcut(QKeySequence(config_scuts["window_browser remove current filter"]), self)
- self.csRemoveFilterScut.activated.connect(self.csRemoveFilterFunc)
-
-# Corresponds to _setup_tools in the SidebarToolbar class in Anki 2.1.45
-sidebar_tool_names = [
- "window_browser sidebar search",
- "window_browser sidebar select"
- ]
-
-
-def cs_sidebar_setup_tools(self):
- from aqt.theme import theme_manager
- for row, tool in enumerate(self._tools):
- action = self.addAction(
- theme_manager.icon_from_resources(tool[1]), tool[2]()
- )
- action.setCheckable(True)
- # If we are aware of the row, set it in the tools
- # otherwise, use the default
- action.setShortcut(
- config_scuts[sidebar_tool_names[row]]
- if row < len(sidebar_tool_names) else
- f"Alt+{row + 1}"
- )
- self._action_group.addAction(action)
- # always start with first tool
- active = 0
- self._action_group.actions()[active].setChecked(True)
- self.sidebar.tool = self._tools[active][0]
-
-def cs_injectCloseShortcut(scuts):
- def inject_shortcut(self):
- try:
- from aqt.utils import is_mac
- isMac = is_mac
- except:
- from aqt.utils import isMac
- cutExistingShortcut = False
- for scut in scuts:
- if scut == "<default>":
- continue
- addedShortcut = False
- if isMac and not cutExistingShortcut:
- for child in self.findChildren(QShortcut):
- if child.key().toString() == 'Ctrl+W':
- child.setKey(scut)
- addedShortcut = cutExistingShortcut = True
- if not addedShortcut:
- shortcut = QShortcut(QKeySequence(scut), self)
- qconnect(shortcut.activated, self.reject)
- setattr(self, "_closeShortcut", shortcut)
- return inject_shortcut
-
-# Functions that execute on startup
-if config_scuts["Ω enable main"].upper() == 'Y':
- Toolbar._centerLinks = cs_toolbarCenterLinks
- cs_main_setupShortcuts()
-if config_scuts["Ω enable editor"].upper() == 'Y':
- Editor.cs_changeDeck = functions.editor_changeDeck
- Editor.sToF = functions.editor_sToF
- Editor.cs_u_onAltCloze = lambda self: functions.cs_editor_generate_cloze(self, altModifier=True)
- Editor.cs_u_onStdCloze = lambda self: functions.cs_editor_generate_cloze(self, altModifier=False)
- Editor.cs_onAltCloze = functions.cs_editor_on_alt_cloze
- Editor.cs_onStdCloze = functions.cs_editor_on_std_cloze
- Editor.customPaste = cs_editor_custom_paste
- Editor._customPaste = cs_uEditor_custom_paste
- Editor.setupShortcuts = cs_editor_setupShortcuts
- Editor.setupShortcuts = wrap(Editor.setupShortcuts, cs_editorChangeDeck)
- if functions.get_version() >= 45:
- Editor.csToggleStickyCurrent = cs_editorToggleStickyCurrent
- Editor.csToggleStickyAll = cs_editorToggleStickyAll
- Editor.onBridgeCmd = wrap(Editor.onBridgeCmd, cs_captureBridgeToggleSticky, "around")
- if notetypechooser_import:
- NotetypeChooser._setup_ui = wrap(NotetypeChooser._setup_ui, cs_editorNotetypeChooser)
- ModelChooser.setupModels = wrap(ModelChooser.setupModels, cs_editorChangeNoteType)
- AddCards.setupButtons = wrap(AddCards.setupButtons, cs_editorAddCard)
- try:
- gui_hooks.add_cards_did_init.append(cs_injectCloseShortcut([config_scuts["editor add card close window"]]))
- except:
- pass
-if config_scuts["Ω enable reviewer"].upper() == 'Y':
- Reviewer._shortcutKeys = wrap(Reviewer._shortcutKeys, cs_review_setupShortcuts, "around")
- Reviewer.sToF = functions.review_sToF
-if config_scuts["Ω enable m_toolbox"].upper() == 'Y':
- cs_mt_setupShortcuts()
-# Hooks to setup shortcuts at the right time
-if config_scuts["Ω enable window_browser"].upper() == 'Y':
- Browser.csRemoveFilterFunc = functions.remove_filter
- Browser.setupEditor = cs_browser_setupEditor
- addHook('browser.setupMenus', cs_browser_setupShortcuts)
- if functions.get_version() >= 45:
- from aqt.browser import SidebarToolbar
- SidebarToolbar._setup_tools = cs_sidebar_setup_tools
-
-# Fun fact: the stats window shortcut can also be customized (very slightly)
-# Due to the added complexity of handling this relative to what is probably zero demand, this will remain unimplemented for the time being
-# gui_hooks.stats_dialog_will_show.append(cs_injectCloseShortcut([config_scuts["stats close window"]]))
-# The deck options window is another feature that probably won't be implemented unless requested
-# gui_hooks.deck_options_did_load.append(cs_injectCloseShortcut([config_scuts["editor deck options close window"]]))
-
-# Detects all conflicts, regardless of enable status
-cs_conflictDetect()
-
-# Redraws the toolbar with the new shortcuts
-mw.toolbar.draw()