What to bind a global shortcut to?

Thanks to help here, I finished a simple (but useful!) add-on. The last step is to try and make the shortcut global.

Looking at the anki codebase, I basically want this: anki/main.py at c21e6e2b97c6df76aebe4d61890b055a8de1dd7e · ankitects/anki · GitHub

but I’m not quite sure how to get at the same object from where I’m calling.

Here’s what I have:

def create_shortcut():
  QShortcut(QKeySequence('u'), aqt.mw, next_deck)


I think it’s just a matter of replacing aqt.mw with the right object, I’m just not sure what that object should be. I want this shortcut to work like ‘d’ or ‘s’ work, so if I’m on a deck screen I can still use it.

Thank you very much!

Edit: if it’s simpler, I’d also be fine with just making it so that this shortcut is also available in the current deck screen, eg the screen you see when you click a deck (or finish studying it). I don’t need it everywhere…that might make it simpler

That should work already. If you add a print statement to your next_deck function and run Anki with a console active, you should see output.


Wrote a reply here, but yeah, looking at this again now, I think the main issue really just is that u is already bound in some mw states. Switching to a different assignment should make the QShortcut solution work!


thank you for taking the time! the shortcut indeed works in the main deck view. it’s not working in the current deck review screen, though…sounds like I need to get a better debug setup :slight_smile: (I’ve been meaning to ask if there is a good way to trace everything going on in the background with anki as that would be very helpful for developing add-ons, perhaps deserves its own thread through) I’m going to paste the code just in case it’s a very easy solution…I will of course keep digging in

def next_deck():
  due_tree = aqt.mw.col.sched.deck_due_tree().children
  def has_reviews(x):
    return x.learn_count > 0 or x.new_count > 0 or x.review_count > 0
  has_due = sorted([(x.name, x.deck_id) for x in due_tree if has_reviews(x)])
  has_due = filter(lambda x: x[0] not in FORBIDDEN, has_due)
  to_select = next(has_due, None)
  if to_select is None:

So I just confirmed (with a showInfo that I inserted at the beginning of this function) that if I am in the screen that comes up when you finish reviewing, that the shortcut does not fire.

So basically, from the main deck screen, I press u. It correctly takes me to the first deck with reviews. I review them all, I am taken to the “you’ve reviewed everything in this deck” screen. I press u again–nothing happens.

1 Like

ack, I was writing my response when you sent this, so I didn’t see it. Thank you for your very informative response on reddit, and this makes sense, I will try out different bindings.

1 Like

per @glutanimate’s post on reddit, I tried the binding “Ctrl+Alt+Shift+U” and what I posted did indeed work…odd. So I guess it is that there is a binding collision. Which is weird, because when I press “u” in the deck overview screen, nothing happens. It’d be very convenient if there were a way to spit out all of the shortcuts currently active on a view…

For avoiding conflicts with native Anki shortcuts I usually look at the source code. Otherwise, and especially when troubleshooting conflicts with other add-ons, I sometimes do a variation of this (run via the debug console):

from aqt import mw
from aqt.qt import QShortcut

sc = mw.findChildren(QShortcut)
print([i.key().toString() for i in sc])

Though this doesn’t reflect all bindings as add-ons or native code might intercept key presses through other means as well.

For what it’s worth, u is bound to unbury (and thus only really does something when there are cards to unbury, which is why it’s a bit easy to miss).