MailJDTourDownloadDocsQualityTestsCoverage

Which source lines and branches the tests execute. Lines 91.5 %, branches 75.0 % (minimum 85 % and 72 %). main @ 399ffe3d · 21 October 2026 · pipeline 7238.

GCC Code Coverage Report


Directory: src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 11 / 0 / 11
Functions: 100.0% 11 / 0 / 11
Branches: -% 0 / 0 / 0

presentation/QuickCommandRouter.h
Line Branch Exec Source
1 #pragma once
2 #include "app/CommandRegistry.h"
3 #include "CommandCompletion.h"
4 #include "CommandHistory.h"
5 #include "CommandBarRowModel.h"
6 #include "KeyOverlayController.h"
7 #include <QAbstractListModel>
8 #include <QKeyEvent>
9 #include <QPointer>
10 #include <QSet>
11 #include <QElapsedTimer>
12 #include <QTimer>
13 #include <QVariantMap>
14
15 class QQuickItem;
16 class QQuickWindow;
17 class WorkspaceState;
18
19 // One instance per window. Shared specs; no second shortcut definition in QML.
20 class QuickCommandRouter final : public QAbstractListModel {
21 Q_OBJECT
22 Q_PROPERTY(QString query READ query WRITE setQuery NOTIFY queryChanged)
23 Q_PROPERTY(QVariantMap availability READ availability NOTIFY availabilityChanged)
24 // Sprint 95: the rule manager page switches the mail area to the Rules context.
25 Q_PROPERTY(bool rulesOpen READ rulesOpen WRITE setRulesOpen NOTIFY rulesOpenChanged)
26 // Sprint 98 G8: the rows of the command bar's panel, updated in place.
27 Q_PROPERTY(CommandBarRowModel *rowModel READ rowModel CONSTANT)
28 // Sprint 105: the keys overlay of this window (S105.8.5).
29 Q_PROPERTY(KeyOverlayController *overlay READ overlay CONSTANT)
30 // S105.7.3: a pending prefix ("g") and what may follow ([{key, text}]).
31 Q_PROPERTY(QString pendingPrefix READ pendingPrefix NOTIFY prefixChanged)
32 Q_PROPERTY(QVariantList prefixChoices READ prefixChoices NOTIFY prefixChanged)
33 public:
34 explicit QuickCommandRouter(QObject *parent = nullptr);
35 1993 CommandBarRowModel *rowModel() { return &m_rowModel; }
36 3417 KeyOverlayController *overlay() { return m_overlay; }
37 QQuickWindow *window() const;
38 QString pendingPrefix() const;
39 QVariantList prefixChoices() const;
40 // Sprint 105 rule 3: the key that runs `id` now, with the current focus
41 // (empty when no key does) — the overlay's badges come from here.
42 QKeySequence effectiveKey(const QString &id) const;
43 Q_INVOKABLE QString effectiveKeyText(const QString &id) const;
44 // S105.9.4: windows this router does not filter (a compose or editor
45 // window of its own) bind their keys with Shortcuts; their controls show
46 // the command's own key (`keyTextOf`) instead of the effective one.
47 Q_INVOKABLE bool filtersWindow(QObject *window) const;
48 Q_INVOKABLE QString keyTextOf(const QString &id) const;
49 // S105.6.4: the command's explanation in the interface language ("" = none).
50 Q_INVOKABLE QString explanationFor(const QString &id) const;
51 // A text field (not a read-only reader) has the focus: only keys marked
52 // whileTyping act (S105.7.4).
53 bool typingFocus() const;
54 // The name of the place the keys act on ("Mail list", "Calendar" …).
55 QString contextTitle() const;
56 // D-15: F6 / Shift+F6 — the next or previous pane (KeyHint.pane).
57 Q_INVOKABLE bool focusPane(int delta);
58 // D-25: F6–F9 — the visible pane with this KeyHint.paneOrder (the
59 // leftmost when several); false when the area shows none.
60 Q_INVOKABLE bool focusPaneAt(int order);
61 // D-25: the command (F6–F9) that focuses panes of this order.
62 static QString paneCommand(int order);
63 // KeyHint.context names → focus contexts ("agenda", "settingsPages", "compose").
64 static CommandContexts focusContextOf(const QString &name);
65 // Sprint 107: a sheet whose focus context replaces the area's (the
66 // conflict resolver) — while it has the focus only its keys act and the
67 // keys overlay annotates only the sheet (the item returned here).
68 14309486 static bool exclusiveContext(CommandContexts context) { return context.testFlag(CommandContext::Resolver); }
69 QQuickItem *exclusiveScope() const;
70 // The keys a pane's focus context adds while it has the focus (the
71 // agenda's j/k/Enter) — empty when that pane has the focus already.
72 QList<const CommandSpec *> paneCommands(const QString &context) const;
73 // G10 (S105.8.8): tests press every key the overlay shows and check what
74 // would run — a dry run reports the command instead of running it.
75 122 void setDryRun(bool dryRun) { m_dryRun = dryRun; }
76 int rowCount(const QModelIndex &parent = {}) const override;
77 QVariant data(const QModelIndex &index, int role) const override;
78 QHash<int, QByteArray> roleNames() const override;
79 1 QString query() const { return m_query; }
80 void setQuery(const QString &query);
81 void attach(QQuickWindow *window);
82 void setContext(CommandContext context);
83 void bindWorkspace(WorkspaceState *workspace);
84 void setSupported(const QSet<QString> &commands);
85 void setNamedSupported(const QSet<QString> &commands);
86 831 bool rulesOpen() const { return m_rulesOpen; }
87 void setRulesOpen(bool open);
88 // Sprint 98 S98.1.4: the command bar's completion for `text` with the
89 // cursor at `cursor`; `states` maps toggle state keys to booleans (the
90 // window owns some of them, e.g. the list filters). The result's
91 // fields are documented in CommandCompletion.h.
92 Q_INVOKABLE QVariantMap completions(const QString &text, int cursor, const QVariantMap &states = {}) const;
93 // S98.4.8: the closest command line for a misspelled one ("" = none).
94 Q_INVOKABLE QString correction(const QString &text) const;
95 // The host installs the data sources (folders, labels, availability …);
96 // without them the bar completes command names as a design preview.
97 void setCompletionSources(const CommandCompletion::Sources &sources);
98 // S98.1.6 (D-9): after a successful run; free-text lines are refused.
99 Q_INVOKABLE bool recordCommand(const QString &line);
100 Q_INVOKABLE void clearHistory();
101 // S98.5.2: Undo of the last clearHistory() (false when there is none).
102 Q_INVOKABLE bool restoreHistory();
103 21 Q_INVOKABLE int historySize() const { return int(m_history.lines().size()); }
104 4 Q_INVOKABLE QStringList historyLines() const { return m_history.lines(); }
105 // D-20: folder switches and move targets of an account.
106 void recordFolder(const QString &account, const QString &path);
107 1116 CommandHistory &history() { return m_history; }
108 // Sprint 98 S98.1.3: what a named line runs — {command, argument, value,
109 // values, words, rest, registryId, stateKey, complete, syntax, inContext}
110 // from the catalog (empty when the first word names no command); values
111 // and words list the parts of a line with several of them (D-15a).
112 Q_INVOKABLE QVariantMap namedTarget(const QString &text) const;
113 Q_INVOKABLE bool canInvokeNamed(const QString &text) const;
114 Q_INVOKABLE QString namedCommandName(const QString &text) const;
115 Q_INVOKABLE bool invokeNamed(const QString &text);
116 QVariantMap availability() const;
117 Q_INVOKABLE bool isAvailable(const QString &id) const;
118 Q_INVOKABLE void cancelSequence();
119 Q_INVOKABLE bool invoke(const QString &id);
120 // True only while a command runs from its keyboard shortcut (Sprint 97:
121 // Ctrl+K focuses the contact search, the area button and the console do not).
122 29 Q_INVOKABLE bool invokedFromKeyboard() const { return m_fromKeyboard; }
123 Q_INVOKABLE QString defaultShortcutFor(const QString &id) const;
124 Q_INVOKABLE bool invokeRow(int row);
125 // S105.9.5: recompute "On this screen" (the help opens).
126 7 Q_INVOKABLE void refreshHelp() { rebuild(); }
127 Q_INVOKABLE QString commandAt(int row) const;
128 Q_INVOKABLE QVariantMap entryAt(int row) const;
129 signals:
130 void invoked(const QString &id);
131 void namedInvoked(const QString &command, const QString &argument);
132 void queryChanged();
133 void availabilityChanged();
134 void rulesOpenChanged();
135 void historyChanged();
136 void prefixChanged();
137 // D-23: a key that means something elsewhere (once per key and session).
138 void keyHintRequested(const QString &text);
139 // D-15: the pane F6 moved to (for the status line).
140 void paneFocused(const QString &name);
141 void dryRunInvoked(const QString &id);
142 public:
143 // F-32 (SPRINT-104): the key event's effective shortcut — the
144 // KeypadModifier is stripped and an unmodified letter matches its
145 // physical (US-layout) key, so keypad keys and non-Latin layouts
146 // trigger the same single-key shortcuts.
147 static QKeySequence normalizedShortcut(const QKeyEvent *key);
148
149 protected:
150 bool eventFilter(QObject *watched, QEvent *event) override;
151 private:
152 bool invokeFromKeyboard(const QString &id);
153 void rebuild();
154 void updateWorkspaceContext();
155 void notifyAvailability();
156 QString m_query;
157 QList<const CommandSpec *> m_commands;
158 int m_screenRows = 0; // the leading "On this screen" rows of m_commands
159 QPointer<QQuickWindow> m_window;
160 QSet<QString> m_supported;
161 QSet<QString> m_namedSupported;
162 QPointer<WorkspaceState> m_workspace;
163 const CommandSpec *commandFor(const QKeySequence &sequence, bool typing) const;
164 CommandContexts activeContexts() const;
165 bool isPrefix(const QKeySequence &sequence) const;
166 void updateFocusContext();
167 void showWrongKeyHint(const QKeySequence &sequence);
168 bool handleKeyPress(QKeyEvent *key);
169 QKeySequence m_prefix;
170 QTimer m_prefixTimeout;
171 QSet<int> m_hintedKeys;
172 CommandContext m_context = CommandContext::MainMail;
173 CommandContexts m_focusContext;
174 KeyOverlayController *m_overlay = nullptr;
175 bool m_dryRun = false;
176 bool m_rulesOpen = false;
177 bool m_fromKeyboard = false;
178 CommandCompletion::Sources m_sources;
179 CommandHistory m_history;
180 CommandBarRowModel m_rowModel{this}; // parented: QML never takes ownership
181 QVariantMap m_clearedHistory;
182 bool m_sourcesInstalled = false;
183 CommandCompletion::Sources effectiveSources(const QVariantMap &states) const;
184 };
185