summaryrefslogtreecommitdiffstats
path: root/src/keymap.cpp
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-03 14:17:09 +0200
committerDanilo M. <danix@danix.xyz>2026-08-04 12:53:19 +0200
commitd7b87856340eefad1fed7d2f246fa49cdcf63d93 (patch)
treeb809a3221d32e0276a3156ac2a2a45ea7f73b825 /src/keymap.cpp
parent8708139212e4f411509e0c11ed9c04de5cf33a22 (diff)
downloadqtmaildir-d7b87856340eefad1fed7d2f246fa49cdcf63d93.tar.gz
qtmaildir-d7b87856340eefad1fed7d2f246fa49cdcf63d93.zip
feat: add menus, a toolbar and a shortcut reference
Actions were a QHash of std::function dispatched by an event filter, which nothing could put in a menu. They are QActions now, bound from KeyMap so a [keys] override reaches the menus as well as the keyboard. Menu bar covers every action; the toolbar carries only Sync, Archive, Delete and Undo. Help > Keyboard shortcuts is generated from the actions, so it shows what the keys really do rather than a copy that drifts. spam and load_remote gained defaults, having been unreachable without a hand-written binding. The event filter is gone. Probing showed QAction shortcuts are dispatched before the focused widget sees the key, so they beat QAbstractItemView's type-to-search without one, and Qt already suppresses plain-letter shortcuts while an editable widget has focus. Dropping the filter's blanket guard also lets Ctrl+Q work while the query bar has focus. registeredActionNames() is derived from the actions rather than hand-maintained, so the two drift tests it needed are replaced by checks that a configured binding reaches its action. No confirmation dialogs: tag mutations still answer to undo.
Diffstat (limited to 'src/keymap.cpp')
-rw-r--r--src/keymap.cpp30
1 files changed, 23 insertions, 7 deletions
diff --git a/src/keymap.cpp b/src/keymap.cpp
index e53c2bf..42ccd40 100644
--- a/src/keymap.cpp
+++ b/src/keymap.cpp
@@ -106,17 +106,33 @@ void KeyMap::loadDefaults()
QKeySequence KeyMap::sequenceFor(const QString &action) const
{
- // Several sequences can point at one action (a default the user did not
- // remove, plus their own addition). QHash iteration order is unspecified,
- // so pick deterministically rather than taking whichever comes first.
+ // Several sequences can reach one action: the built-in default, which
+ // loadOverrides() does not remove, plus whatever the user added. Their
+ // binding is the one to show and to put on the QAction, or configuring
+ // "Ctrl+Alt+A = archive" would leave the menu still advertising Ctrl+E.
+ //
+ // QHash iteration order is unspecified, so ties are broken on the text
+ // rather than left to chance.
+ const QKeySequence builtIn = defaultSequenceFor(action);
QKeySequence best;
+ bool bestIsBuiltIn = false;
+
for (auto it = m_bindings.cbegin(); it != m_bindings.cend(); ++it) {
if (it.value() != action)
continue;
- const QString candidate = it.key().toString();
- if (best.isEmpty() || candidate.size() < best.toString().size()
- || (candidate.size() == best.toString().size()
- && candidate < best.toString())) {
+
+ const bool isBuiltIn = !builtIn.isEmpty() && it.key() == builtIn;
+ if (best.isEmpty()) {
+ best = it.key();
+ bestIsBuiltIn = isBuiltIn;
+ continue;
+ }
+ // A user binding always beats the default.
+ if (bestIsBuiltIn && !isBuiltIn) {
+ best = it.key();
+ bestIsBuiltIn = false;
+ } else if (bestIsBuiltIn == isBuiltIn
+ && it.key().toString() < best.toString()) {
best = it.key();
}
}