quick/CommandBarSources.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "CommandBarSources.h" | ||
| 2 | |||
| 3 | #include "app/core/CalendarSyncCoordinator.h" | ||
| 4 | #include "app/core/MailSessionCore.h" | ||
| 5 | #include "presentation/FolderPresentationModel.h" | ||
| 6 | #include "presentation/QuickCommandRouter.h" | ||
| 7 | #include "presentation/QuickContactModel.h" | ||
| 8 | #include "presentation/QuickMailBackend.h" | ||
| 9 | #include "presentation/QuickPimBackend.h" | ||
| 10 | #include "presentation/QuickTaskModel.h" | ||
| 11 | #include "presentation/SearchTermModel.h" | ||
| 12 | #include "ui/LabelDelegate.h" | ||
| 13 | #include "presentation/EventQuickInput.h" | ||
| 14 | #include "presentation/QuickRulesBackend.h" | ||
| 15 | #include "presentation/QuickTaskActions.h" | ||
| 16 | #include "presentation/QuickAccountSettings.h" | ||
| 17 | #include "presentation/SettingsCatalog.h" | ||
| 18 | #include <QSet> | ||
| 19 | #include <QCoreApplication> | ||
| 20 | #include <QHash> | ||
| 21 | #include <QLocale> | ||
| 22 | |||
| 23 | // Named namespace: lupdate takes it as the translation context of tr(). | ||
| 24 | namespace CommandBarSourcesText { | ||
| 25 | |||
| 26 | 244 | QString tr(const char *text) { return QCoreApplication::translate("CommandBarSourcesText", text); } | |
| 27 | 98 | QString tr(const char *text, const char *comment, int count) { | |
| 28 | 98 | return QCoreApplication::translate("CommandBarSourcesText", text, comment, count); | |
| 29 | } | ||
| 30 | |||
| 31 | 89 | QList<CommandCompletion::FolderEntry> folders(QuickMailBackend &backend, QuickCommandRouter &router, | |
| 32 | const QString &text, bool move) { | ||
| 33 | 89 | auto *model = static_cast<FolderPresentationModel *>(backend.folders()); | |
| 34 | 89 | QStringList preferred; | |
| 35 |
2/2✓ Branch 3 → 4 taken 26 times.
✓ Branch 3 → 21 taken 63 times.
|
89 | if (move) { |
| 36 |
3/3✓ Branch 4 → 5 taken 26 times.
✓ Branch 9 → 10 taken 26 times.
✓ Branch 10 → 11 taken 26 times.
|
52 | const QString target = backend.suggestion().value(QStringLiteral("target")).toString(); |
| 37 |
3/3✓ Branch 17 → 18 taken 2 times.
✓ Branch 17 → 19 taken 24 times.
✓ Branch 18 → 19 taken 2 times.
|
26 | if (!target.isEmpty()) preferred << target; |
| 38 | 26 | } | |
| 39 | 89 | QList<CommandCompletion::FolderEntry> result; | |
| 40 | const auto candidates = | ||
| 41 |
2/2✓ Branch 22 → 23 taken 89 times.
✓ Branch 24 → 25 taken 89 times.
|
89 | model->completionCandidates(text, preferred, router.history().recentFolders(backend.accountName())); |
| 42 |
2/2✓ Branch 37 → 29 taken 178 times.
✓ Branch 37 → 38 taken 89 times.
|
267 | for (const auto &folder : candidates) |
| 43 | 178 | result.append({folder.path, folder.name, folder.parent, folder.unread, folder.suggested}); | |
| 44 | 89 | return result; | |
| 45 | 267 | } | |
| 46 | |||
| 47 | // D-19: the five standard labels under the names of the label menu, then | ||
| 48 | // the keywords of the selected message that are not standard labels. | ||
| 49 | 30 | QList<CommandCompletion::LabelEntry> labels(QuickMailBackend &backend) { | |
| 50 | 30 | QList<CommandCompletion::LabelEntry> result; | |
| 51 |
1/1✓ Branch 2 → 3 taken 30 times.
|
30 | const QStringList selected = backend.selectedLabels(); |
| 52 |
2/2✓ Branch 21 → 4 taken 150 times.
✓ Branch 21 → 22 taken 30 times.
|
180 | for (int i = 1; i <= 5; ++i) { |
| 53 |
1/1✓ Branch 8 → 9 taken 150 times.
|
300 | const QString keyword = QStringLiteral("$label%1").arg(i); |
| 54 | 150 | result.append({keyword, tr("Label %1").arg(i), | |
| 55 | 150 | selected.contains(keyword, Qt::CaseInsensitive)}); | |
| 56 | 150 | } | |
| 57 |
2/2✓ Branch 39 → 24 taken 6 times.
✓ Branch 39 → 40 taken 30 times.
|
36 | for (const QString &keyword : selected) |
| 58 |
2/3✓ Branch 28 → 29 taken 6 times.
✓ Branch 31 → 32 taken 6 times.
✗ Branch 31 → 37 not taken.
|
12 | if (!keyword.startsWith(QStringLiteral("$label"), Qt::CaseInsensitive)) result.append({keyword, keyword, true}); |
| 59 | 30 | return result; | |
| 60 | 486 | } | |
| 61 | |||
| 62 | // D-21: writable task lists; a name that repeats across accounts carries | ||
| 63 | // its account so "/List@Account" can be inserted. | ||
| 64 | 5 | QList<CommandCompletion::TaskListEntry> taskLists(MailSessionCore &session) { | |
| 65 | 5 | QList<CommandCompletion::TaskListEntry> result; | |
| 66 | 5 | auto *sync = session.calendarSync(); | |
| 67 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 5 times.
|
5 | if (!sync) return result; |
| 68 | 5 | QHash<QString, int> names; | |
| 69 |
1/1✓ Branch 5 → 6 taken 5 times.
|
5 | const auto calendars = sync->calendars(); |
| 70 |
2/2✓ Branch 21 → 8 taken 6 times.
✓ Branch 21 → 22 taken 5 times.
|
11 | for (const auto &calendar : calendars) |
| 71 |
6/9✓ Branch 9 → 10 taken 6 times.
✗ Branch 9 → 13 not taken.
✓ Branch 10 → 11 taken 6 times.
✓ Branch 11 → 12 taken 6 times.
✗ Branch 11 → 13 not taken.
✓ Branch 14 → 15 taken 6 times.
✗ Branch 14 → 19 not taken.
✓ Branch 15 → 16 taken 6 times.
✓ Branch 16 → 17 taken 6 times.
|
6 | if (!calendar.readOnly && calendar.supportsTasks()) ++names[calendar.displayName.toLower()]; |
| 72 |
2/2✓ Branch 41 → 24 taken 6 times.
✓ Branch 41 → 42 taken 5 times.
|
11 | for (const auto &calendar : calendars) |
| 73 |
4/7✓ Branch 25 → 26 taken 6 times.
✗ Branch 25 → 29 not taken.
✓ Branch 26 → 27 taken 6 times.
✓ Branch 27 → 28 taken 6 times.
✗ Branch 27 → 29 not taken.
✓ Branch 30 → 31 taken 6 times.
✗ Branch 30 → 39 not taken.
|
6 | if (!calendar.readOnly && calendar.supportsTasks()) |
| 74 | 12 | result.append({calendar.displayName, calendar.accountId, names.value(calendar.displayName.toLower()) > 1}); | |
| 75 | 5 | return result; | |
| 76 | 17 | } | |
| 77 | |||
| 78 | ✗ | QStringList tags(QuickMailBackend &backend) { | |
| 79 | ✗ | QStringList result; | |
| 80 | ✗ | const QVariantMap counts = backend.pim()->taskModel().counts(); | |
| 81 | ✗ | for (auto it = counts.cbegin(); it != counts.cend(); ++it) | |
| 82 | ✗ | if (it.key().startsWith(QStringLiteral("tag:"))) result.append(it.key().mid(4)); | |
| 83 | ✗ | return result; | |
| 84 | ✗ | } | |
| 85 | |||
| 86 | // The contact completion lane is asynchronous (latest wins): the request | ||
| 87 | // starts here, the rows of the last finished answer that still match are | ||
| 88 | // returned; the window recomputes on completionsChanged. | ||
| 89 | 10 | QList<CommandCompletion::AddressEntry> addresses(QuickMailBackend &backend, const QString &prefix) { | |
| 90 | 10 | auto &contacts = backend.pim()->contactModel(); | |
| 91 | 10 | contacts.requestCompletions(prefix); | |
| 92 | 10 | QList<CommandCompletion::AddressEntry> result; | |
| 93 |
4/4✓ Branch 6 → 7 taken 10 times.
✓ Branch 7 → 8 taken 10 times.
✓ Branch 93 → 9 taken 1 time.
✓ Branch 93 → 94 taken 10 times.
|
11 | for (const QVariant &value : contacts.completions()) { |
| 94 |
1/1✓ Branch 10 → 11 taken 1 time.
|
1 | const QVariantMap entry = value.toMap(); |
| 95 |
2/2✓ Branch 15 → 16 taken 1 time.
✓ Branch 16 → 17 taken 1 time.
|
2 | const QString address = entry.value(QStringLiteral("email")).toString(); |
| 96 |
9/24✓ Branch 22 → 23 taken 1 time.
✗ Branch 22 → 30 not taken.
✓ Branch 27 → 28 taken 1 time.
✓ Branch 28 → 29 taken 1 time.
✗ Branch 29 → 30 not taken.
✓ Branch 29 → 31 taken 1 time.
✓ Branch 32 → 33 taken 1 time.
✗ Branch 32 → 34 not taken.
✓ Branch 34 → 35 taken 1 time.
✗ Branch 34 → 36 not taken.
✓ Branch 36 → 37 taken 1 time.
✗ Branch 36 → 38 not taken.
✓ Branch 38 → 39 taken 1 time.
✗ Branch 38 → 40 not taken.
✗ Branch 40 → 41 not taken.
✓ Branch 40 → 42 taken 1 time.
✗ Branch 109 → 110 not taken.
✗ Branch 109 → 111 not taken.
✗ Branch 113 → 114 not taken.
✗ Branch 113 → 115 not taken.
✗ Branch 117 → 118 not taken.
✗ Branch 117 → 119 not taken.
✗ Branch 121 → 122 not taken.
✗ Branch 121 → 123 not taken.
|
2 | if (address.isEmpty() || entry.value(QStringLiteral("group")).toBool()) continue; |
| 97 |
2/2✓ Branch 46 → 47 taken 1 time.
✓ Branch 47 → 48 taken 1 time.
|
2 | const QString name = entry.value(QStringLiteral("name")).toString(); |
| 98 |
3/8✓ Branch 52 → 53 taken 1 time.
✗ Branch 53 → 54 not taken.
✓ Branch 53 → 57 taken 1 time.
✗ Branch 54 → 55 not taken.
✗ Branch 55 → 56 not taken.
✗ Branch 55 → 57 not taken.
✗ Branch 58 → 59 not taken.
✓ Branch 58 → 60 taken 1 time.
|
1 | if (!address.contains(prefix, Qt::CaseInsensitive) && !name.contains(prefix, Qt::CaseInsensitive)) continue; |
| 99 |
2/3✗ Branch 62 → 63 not taken.
✓ Branch 62 → 64 taken 1 time.
✓ Branch 69 → 70 taken 1 time.
|
3 | result.append({address, name == address ? QString{} : name, entry.value(QStringLiteral("detail")).toString()}); |
| 100 | 11 | } | |
| 101 | 10 | return result; | |
| 102 | 3 | } | |
| 103 | |||
| 104 | // S98.1.11: the structured rows of the debounced preview lane. | ||
| 105 | 201 | QList<CommandCompletion::ResultEntry> results(QuickMailBackend &backend) { | |
| 106 | 201 | QList<CommandCompletion::ResultEntry> result; | |
| 107 | 201 | int index = 0; | |
| 108 |
4/4✓ Branch 3 → 4 taken 201 times.
✓ Branch 4 → 5 taken 201 times.
✓ Branch 44 → 6 taken 125 times.
✓ Branch 44 → 45 taken 201 times.
|
326 | for (const QVariant &value : backend.searchSuggestions()) { |
| 109 |
1/1✓ Branch 7 → 8 taken 125 times.
|
125 | const QVariantMap entry = value.toMap(); |
| 110 |
1/1✓ Branch 13 → 14 taken 125 times.
|
375 | result.append({QString::number(index++), entry.value(QStringLiteral("subject")).toString(), |
| 111 |
1/1✓ Branch 19 → 20 taken 125 times.
|
250 | entry.value(QStringLiteral("from")).toString(), QString{}, |
| 112 |
1/1✓ Branch 25 → 26 taken 125 times.
|
250 | entry.value(QStringLiteral("folderPath")).toString()}); |
| 113 | 326 | } | |
| 114 | 201 | return result; | |
| 115 | 500 | } | |
| 116 | |||
| 117 | |||
| 118 | 349 | QVariantMap chip(const QString &label, const QString &text, bool ok = true, const QString &reason = {}) { | |
| 119 | 1396 | return {{QStringLiteral("label"), label}, {QStringLiteral("text"), text}, {QStringLiteral("ok"), ok}, | |
| 120 |
2/4✓ Branch 20 → 21 taken 1396 times.
✓ Branch 20 → 22 taken 349 times.
✗ Branch 33 → 34 not taken.
✗ Branch 33 → 35 not taken.
|
2443 | {QStringLiteral("reason"), reason}}; |
| 121 | 1745 | } | |
| 122 | |||
| 123 | // S98.4.12: one chip per part the parser recognised; a rejected part is a | ||
| 124 | // chip with ok = false and the reason. Every parser is the one that runs | ||
| 125 | // the line (rule 8). | ||
| 126 | 26 | QVariantList taskPreview(QuickMailBackend &backend, const QString &line) { | |
| 127 |
1/1✓ Branch 4 → 5 taken 26 times.
|
26 | const QVariantMap parts = backend.pim()->taskActions()->previewInput(line); |
| 128 | 26 | QVariantList chips; | |
| 129 | // A token still being typed (the last word, no space after it) is not | ||
| 130 | // rejected yet: "@mor" becomes "@morgen" with Tab. | ||
| 131 |
4/4✓ Branch 7 → 8 taken 26 times.
✓ Branch 8 → 9 taken 5 times.
✓ Branch 8 → 10 taken 21 times.
✓ Branch 13 → 14 taken 21 times.
|
47 | const QString typing = line.endsWith(QLatin1Char(' ')) ? QString{} : line.section(QLatin1Char(' '), -1); |
| 132 | 45 | const auto settled = [&](QChar marker, const char *okKey) { | |
| 133 |
11/20✓ Branch 4 → 5 taken 45 times.
✓ Branch 5 → 6 taken 45 times.
✓ Branch 6 → 7 taken 45 times.
✓ Branch 7 → 8 taken 13 times.
✓ Branch 7 → 10 taken 32 times.
✓ Branch 8 → 9 taken 13 times.
✓ Branch 9 → 10 taken 11 times.
✓ Branch 9 → 11 taken 2 times.
✓ Branch 13 → 14 taken 45 times.
✗ Branch 13 → 15 not taken.
✓ Branch 15 → 16 taken 45 times.
✗ Branch 15 → 17 not taken.
✓ Branch 17 → 18 taken 45 times.
✗ Branch 17 → 19 not taken.
✗ Branch 21 → 22 not taken.
✗ Branch 21 → 23 not taken.
✗ Branch 25 → 26 not taken.
✗ Branch 25 → 27 not taken.
✗ Branch 30 → 31 not taken.
✗ Branch 30 → 32 not taken.
|
45 | return parts.value(QLatin1String(okKey)).toBool() || typing.startsWith(marker); |
| 134 | 26 | }; | |
| 135 |
2/2✓ Branch 18 → 19 taken 26 times.
✓ Branch 19 → 20 taken 26 times.
|
52 | const QVariantMap target = parts.value(QStringLiteral("target")).toMap(); |
| 136 |
2/2✓ Branch 28 → 29 taken 26 times.
✓ Branch 29 → 30 taken 26 times.
|
52 | const QString list = parts.value(QStringLiteral("list")).toString(); |
| 137 |
5/7✓ Branch 35 → 36 taken 7 times.
✓ Branch 35 → 38 taken 19 times.
✓ Branch 36 → 37 taken 7 times.
✓ Branch 37 → 38 taken 7 times.
✗ Branch 37 → 39 not taken.
✓ Branch 40 → 41 taken 26 times.
✗ Branch 40 → 88 not taken.
|
26 | if (!list.isEmpty() || !target.isEmpty()) |
| 138 |
8/8✓ Branch 52 → 53 taken 26 times.
✓ Branch 53 → 54 taken 26 times.
✓ Branch 55 → 56 taken 2 times.
✓ Branch 55 → 57 taken 24 times.
✓ Branch 56 → 63 taken 2 times.
✓ Branch 62 → 63 taken 24 times.
✓ Branch 63 → 64 taken 26 times.
✓ Branch 64 → 65 taken 26 times.
|
102 | chips << chip(tr("List"), target.value(QStringLiteral("name")).toString().isEmpty() ? list.mid(1) |
| 139 |
9/17✓ Branch 61 → 62 taken 24 times.
✓ Branch 71 → 72 taken 24 times.
✓ Branch 71 → 73 taken 2 times.
✓ Branch 73 → 74 taken 24 times.
✓ Branch 73 → 75 taken 2 times.
✓ Branch 75 → 76 taken 24 times.
✓ Branch 75 → 77 taken 2 times.
✓ Branch 77 → 78 taken 24 times.
✓ Branch 77 → 79 taken 2 times.
✗ Branch 241 → 242 not taken.
✗ Branch 241 → 243 not taken.
✗ Branch 245 → 246 not taken.
✗ Branch 245 → 247 not taken.
✗ Branch 249 → 250 not taken.
✗ Branch 249 → 251 not taken.
✗ Branch 253 → 254 not taken.
✗ Branch 253 → 255 not taken.
|
74 | : target.value(QStringLiteral("name")).toString(), |
| 140 |
5/5✓ Branch 41 → 42 taken 26 times.
✓ Branch 43 → 44 taken 26 times.
✓ Branch 44 → 45 taken 26 times.
✓ Branch 47 → 48 taken 26 times.
✓ Branch 66 → 67 taken 26 times.
|
104 | settled(QLatin1Char('/'), "listOk"), tr("No task list “%1”").arg(list.mid(1))); |
| 141 | // An unfinished token shows as typed, not as the parser's verdict. | ||
| 142 | 19 | const auto shown = [&](QChar marker, const char *okKey, const QString &parsed) { | |
| 143 |
12/21✓ Branch 4 → 5 taken 19 times.
✓ Branch 5 → 6 taken 19 times.
✓ Branch 6 → 7 taken 19 times.
✓ Branch 7 → 8 taken 11 times.
✓ Branch 7 → 12 taken 8 times.
✓ Branch 8 → 9 taken 11 times.
✓ Branch 9 → 10 taken 10 times.
✓ Branch 9 → 12 taken 1 time.
✓ Branch 10 → 11 taken 10 times.
✓ Branch 14 → 15 taken 19 times.
✗ Branch 14 → 16 not taken.
✓ Branch 16 → 17 taken 19 times.
✗ Branch 16 → 18 not taken.
✓ Branch 18 → 19 taken 19 times.
✗ Branch 18 → 20 not taken.
✗ Branch 22 → 23 not taken.
✗ Branch 22 → 24 not taken.
✗ Branch 26 → 27 not taken.
✗ Branch 26 → 28 not taken.
✗ Branch 31 → 32 not taken.
✗ Branch 31 → 33 not taken.
|
38 | return !parts.value(QLatin1String(okKey)).toBool() && typing.startsWith(marker) ? typing.mid(1) : parsed; |
| 144 | 26 | }; | |
| 145 |
4/4✓ Branch 92 → 93 taken 26 times.
✓ Branch 93 → 94 taken 26 times.
✓ Branch 100 → 101 taken 14 times.
✓ Branch 100 → 129 taken 12 times.
|
52 | if (!parts.value(QStringLiteral("due")).toString().isEmpty()) |
| 146 |
5/5✓ Branch 109 → 110 taken 14 times.
✓ Branch 110 → 111 taken 14 times.
✓ Branch 113 → 114 taken 14 times.
✓ Branch 114 → 115 taken 14 times.
✓ Branch 115 → 116 taken 14 times.
|
42 | chips << chip(tr("Due"), shown(QLatin1Char('@'), "dueOk", parts.value(QStringLiteral("due")).toString()), |
| 147 |
2/2✓ Branch 104 → 105 taken 14 times.
✓ Branch 117 → 118 taken 14 times.
|
42 | settled(QLatin1Char('@'), "dueOk")); |
| 148 |
4/4✓ Branch 133 → 134 taken 26 times.
✓ Branch 134 → 135 taken 26 times.
✓ Branch 141 → 142 taken 5 times.
✓ Branch 141 → 170 taken 21 times.
|
52 | if (!parts.value(QStringLiteral("priority")).toString().isEmpty()) |
| 149 |
5/5✓ Branch 150 → 151 taken 5 times.
✓ Branch 151 → 152 taken 5 times.
✓ Branch 154 → 155 taken 5 times.
✓ Branch 155 → 156 taken 5 times.
✓ Branch 156 → 157 taken 5 times.
|
15 | chips << chip(tr("Priority"), shown(QLatin1Char('!'), "priorityOk", parts.value(QStringLiteral("priorityText")).toString()), |
| 150 |
2/2✓ Branch 145 → 146 taken 5 times.
✓ Branch 158 → 159 taken 5 times.
|
15 | settled(QLatin1Char('!'), "priorityOk")); |
| 151 |
5/8✓ Branch 174 → 175 taken 26 times.
✓ Branch 175 → 176 taken 26 times.
✓ Branch 180 → 181 taken 26 times.
✓ Branch 181 → 182 taken 26 times.
✗ Branch 186 → 187 not taken.
✗ Branch 188 → 189 not taken.
✗ Branch 195 → 183 not taken.
✓ Branch 195 → 196 taken 26 times.
|
52 | for (const QString &tag : parts.value(QStringLiteral("tags")).toStringList()) chips << chip(QString{}, tag); |
| 152 | 26 | return chips; | |
| 153 | 26 | } | |
| 154 | |||
| 155 | 5 | QVariantList eventPreview(QuickMailBackend &backend, const QString &line) { | |
| 156 |
1/1✓ Branch 3 → 4 taken 5 times.
|
5 | const QVariantMap parsed = backend.eventInput()->parse(line); |
| 157 | 5 | QVariantList chips; | |
| 158 |
2/11✓ Branch 7 → 8 taken 5 times.
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 34 taken 5 times.
✗ Branch 16 → 17 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 18 → 19 not taken.
✗ Branch 19 → 20 not taken.
✗ Branch 23 → 24 not taken.
✗ Branch 23 → 25 not taken.
✗ Branch 202 → 203 not taken.
✗ Branch 202 → 204 not taken.
|
5 | if (parsed.contains(QStringLiteral("error"))) return {chip(tr("Calendar"), parsed.value(QStringLiteral("error")).toString(), false)}; |
| 159 |
3/4✓ Branch 38 → 39 taken 5 times.
✓ Branch 39 → 40 taken 5 times.
✓ Branch 46 → 47 taken 5 times.
✗ Branch 46 → 68 not taken.
|
10 | if (!parsed.value(QStringLiteral("summary")).toString().isEmpty()) |
| 160 |
5/5✓ Branch 52 → 53 taken 5 times.
✓ Branch 53 → 54 taken 5 times.
✓ Branch 54 → 55 taken 5 times.
✓ Branch 55 → 56 taken 5 times.
✓ Branch 57 → 58 taken 5 times.
|
10 | chips << chip(tr("Title"), parsed.value(QStringLiteral("summary")).toString()); |
| 161 |
2/3✓ Branch 71 → 72 taken 5 times.
✓ Branch 74 → 75 taken 5 times.
✗ Branch 74 → 106 not taken.
|
5 | if (parsed.contains(QStringLiteral("dateIso"))) |
| 162 |
7/7✓ Branch 76 → 77 taken 5 times.
✓ Branch 84 → 85 taken 5 times.
✓ Branch 85 → 86 taken 5 times.
✓ Branch 86 → 87 taken 5 times.
✓ Branch 87 → 88 taken 5 times.
✓ Branch 88 → 89 taken 5 times.
✓ Branch 89 → 90 taken 5 times.
|
25 | chips << chip(tr("Date"), QLocale().toString(QDate::fromString(parsed.value(QStringLiteral("dateIso")).toString(), Qt::ISODate), |
| 163 |
1/1✓ Branch 91 → 92 taken 5 times.
|
20 | QStringLiteral("ddd d MMM"))); |
| 164 |
2/3✓ Branch 109 → 110 taken 5 times.
✓ Branch 112 → 113 taken 5 times.
✗ Branch 112 → 162 not taken.
|
5 | if (parsed.contains(QStringLiteral("startTime"))) |
| 165 |
4/4✓ Branch 131 → 132 taken 5 times.
✓ Branch 132 → 133 taken 5 times.
✓ Branch 134 → 135 taken 5 times.
✓ Branch 135 → 136 taken 5 times.
|
25 | chips << chip(tr("Time"), parsed.value(QStringLiteral("startTime")).toString() + |
| 166 |
1/1✓ Branch 117 → 118 taken 5 times.
|
10 | (parsed.contains(QStringLiteral("endTime")) |
| 167 |
8/27✗ Branch 118 → 119 not taken.
✓ Branch 118 → 126 taken 5 times.
✗ Branch 123 → 124 not taken.
✗ Branch 124 → 125 not taken.
✗ Branch 125 → 127 not taken.
✓ Branch 133 → 134 taken 5 times.
✓ Branch 137 → 138 taken 5 times.
✗ Branch 148 → 149 not taken.
✓ Branch 148 → 150 taken 5 times.
✗ Branch 150 → 151 not taken.
✓ Branch 150 → 152 taken 5 times.
✗ Branch 152 → 153 not taken.
✓ Branch 152 → 154 taken 5 times.
✗ Branch 154 → 155 not taken.
✓ Branch 154 → 156 taken 5 times.
✗ Branch 156 → 157 not taken.
✓ Branch 156 → 158 taken 5 times.
✗ Branch 352 → 353 not taken.
✗ Branch 352 → 354 not taken.
✗ Branch 356 → 357 not taken.
✗ Branch 356 → 358 not taken.
✗ Branch 360 → 361 not taken.
✗ Branch 360 → 362 not taken.
✗ Branch 364 → 365 not taken.
✗ Branch 364 → 366 not taken.
✗ Branch 368 → 369 not taken.
✗ Branch 368 → 370 not taken.
|
25 | ? "–" + parsed.value(QStringLiteral("endTime")).toString() : QString{})); |
| 168 |
2/8✓ Branch 165 → 166 taken 5 times.
✗ Branch 168 → 169 not taken.
✓ Branch 168 → 190 taken 5 times.
✗ Branch 174 → 175 not taken.
✗ Branch 175 → 176 not taken.
✗ Branch 176 → 177 not taken.
✗ Branch 177 → 178 not taken.
✗ Branch 179 → 180 not taken.
|
5 | if (parsed.contains(QStringLiteral("location"))) chips << chip(tr("Place"), parsed.value(QStringLiteral("location")).toString()); |
| 169 | 5 | return chips; | |
| 170 | 5 | } | |
| 171 | |||
| 172 | // S101.6.5 (D-24, CB-04): the search tab's chips, word for word. | ||
| 173 | 201 | QVariantList searchPreview(const QString &line) { | |
| 174 | 201 | SearchTermModel::Lookups lookups; | |
| 175 | 201 | lookups.label = [](const QString &keyword) { return LabelDelegate::displayName(keyword); }; | |
| 176 | 201 | QVariantList chips; | |
| 177 |
8/8✓ Branch 4 → 5 taken 201 times.
✓ Branch 5 → 6 taken 201 times.
✓ Branch 7 → 8 taken 201 times.
✓ Branch 8 → 9 taken 201 times.
✓ Branch 13 → 14 taken 243 times.
✓ Branch 15 → 16 taken 243 times.
✓ Branch 22 → 10 taken 243 times.
✓ Branch 22 → 23 taken 201 times.
|
444 | for (const auto &term : SearchTermModel::terms(line, lookups)) chips << chip(QString{}, term.label); |
| 178 | 201 | return chips; | |
| 179 | 201 | } | |
| 180 | |||
| 181 | 16 | QVariantList rulePreview(QuickMailBackend &backend, const QString &line) { | |
| 182 |
8/33✓ Branch 5 → 6 taken 16 times.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 17 taken 16 times.
✗ Branch 10 → 11 not taken.
✗ Branch 11 → 12 not taken.
✗ Branch 11 → 17 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 16 → 17 not taken.
✗ Branch 16 → 18 not taken.
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 21 taken 16 times.
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 23 taken 16 times.
✗ Branch 23 → 24 not taken.
✓ Branch 23 → 25 taken 16 times.
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 27 taken 16 times.
✓ Branch 27 → 28 taken 16 times.
✗ Branch 27 → 29 not taken.
✓ Branch 29 → 30 taken 16 times.
✗ Branch 29 → 31 not taken.
✗ Branch 107 → 108 not taken.
✗ Branch 107 → 109 not taken.
✗ Branch 111 → 112 not taken.
✗ Branch 111 → 113 not taken.
✗ Branch 115 → 116 not taken.
✗ Branch 115 → 117 not taken.
✗ Branch 119 → 120 not taken.
✗ Branch 119 → 121 not taken.
✗ Branch 123 → 124 not taken.
✗ Branch 123 → 125 not taken.
✗ Branch 127 → 128 not taken.
✗ Branch 127 → 129 not taken.
|
32 | const bool arrow = line.contains(QStringLiteral("→")) || line.contains(QStringLiteral("->")) || line.contains(QStringLiteral("=>")); |
| 183 |
5/6✓ Branch 31 → 32 taken 16 times.
✗ Branch 31 → 35 not taken.
✓ Branch 34 → 35 taken 1 time.
✓ Branch 34 → 36 taken 15 times.
✓ Branch 37 → 38 taken 1 time.
✓ Branch 37 → 39 taken 15 times.
|
16 | if (!arrow || !backend.rules()->available()) return {}; |
| 184 |
1/1✓ Branch 40 → 41 taken 15 times.
|
15 | const QVariantMap parsed = backend.rules()->parseConsoleRule(line); |
| 185 |
9/11✓ Branch 45 → 46 taken 15 times.
✓ Branch 46 → 47 taken 15 times.
✓ Branch 51 → 52 taken 7 times.
✓ Branch 51 → 75 taken 8 times.
✓ Branch 57 → 58 taken 7 times.
✓ Branch 58 → 59 taken 7 times.
✓ Branch 60 → 61 taken 7 times.
✓ Branch 64 → 65 taken 7 times.
✓ Branch 64 → 66 taken 7 times.
✗ Branch 144 → 145 not taken.
✗ Branch 144 → 146 not taken.
|
58 | if (!parsed.value(QStringLiteral("ok")).toBool()) return {chip(QString{}, parsed.value(QStringLiteral("error")).toString(), false)}; |
| 186 | 8 | QVariantList chips; | |
| 187 |
8/8✓ Branch 79 → 80 taken 8 times.
✓ Branch 80 → 81 taken 8 times.
✓ Branch 85 → 86 taken 8 times.
✓ Branch 86 → 87 taken 8 times.
✓ Branch 91 → 92 taken 39 times.
✓ Branch 93 → 94 taken 39 times.
✓ Branch 100 → 88 taken 39 times.
✓ Branch 100 → 101 taken 8 times.
|
55 | for (const QString &part : parsed.value(QStringLiteral("preview")).toStringList()) chips << chip(QString{}, part); |
| 188 | 8 | return chips; | |
| 189 | 29 | } | |
| 190 | |||
| 191 | // S98.5.8: descriptions that name what a command acts on — the selected | ||
| 192 | // messages and the current folder, both already held by the backend (no | ||
| 193 | // extra query). "" keeps the catalog's description. | ||
| 194 | 2262 | QString contextDetail(QuickMailBackend &backend, const QString &line) { | |
| 195 |
1/1✓ Branch 5 → 6 taken 2262 times.
|
2262 | const QString name = line.section(QLatin1Char(' '), 0, 0); |
| 196 |
1/1✓ Branch 9 → 10 taken 2262 times.
|
2262 | const QString value = line.section(QLatin1Char(' '), 1, 1); |
| 197 |
1/1✓ Branch 13 → 14 taken 2262 times.
|
2262 | const QString rest = line.section(QLatin1Char(' '), 1); |
| 198 |
1/1✓ Branch 14 → 15 taken 2262 times.
|
2262 | const int count = int(backend.selectionCount()); |
| 199 | 2262 | const QString folder = backend.folderPath(); | |
| 200 | // One message keeps the catalog text; with several selected the mail | ||
| 201 | // actions act on all of them (MAIL-SELECTION-ACTIONS) and say how many. | ||
| 202 |
2/2✓ Branch 16 → 17 taken 166 times.
✓ Branch 16 → 109 taken 2096 times.
|
2262 | if (count > 1) { |
| 203 |
3/3✓ Branch 19 → 20 taken 24 times.
✓ Branch 19 → 22 taken 142 times.
✓ Branch 20 → 21 taken 24 times.
|
166 | if (name == QLatin1String("archive")) return tr("Archive %n messages", nullptr, count); |
| 204 |
3/3✓ Branch 24 → 25 taken 2 times.
✓ Branch 24 → 27 taken 140 times.
✓ Branch 25 → 26 taken 2 times.
|
142 | if (name == QLatin1String("delete")) return tr("Move %n messages to the trash", nullptr, count); |
| 205 |
1/3✗ Branch 29 → 30 not taken.
✓ Branch 29 → 32 taken 140 times.
✗ Branch 30 → 31 not taken.
|
140 | if (name == QLatin1String("junk")) return tr("Mark %n messages as junk", nullptr, count); |
| 206 |
4/6✓ Branch 34 → 35 taken 17 times.
✓ Branch 34 → 38 taken 123 times.
✗ Branch 36 → 37 not taken.
✓ Branch 36 → 38 taken 17 times.
✗ Branch 39 → 40 not taken.
✓ Branch 39 → 45 taken 140 times.
|
140 | if (name == QLatin1String("move") && !rest.isEmpty()) |
| 207 | ✗ | return tr("Move %n messages to %1", nullptr, count).arg(rest); | |
| 208 |
3/3✓ Branch 47 → 48 taken 17 times.
✓ Branch 47 → 50 taken 123 times.
✓ Branch 48 → 49 taken 17 times.
|
140 | if (name == QLatin1String("move")) return tr("Move %n messages to a folder", nullptr, count); |
| 209 |
7/7✓ Branch 52 → 53 taken 30 times.
✓ Branch 52 → 57 taken 93 times.
✓ Branch 55 → 56 taken 1 time.
✓ Branch 55 → 57 taken 29 times.
✓ Branch 58 → 59 taken 1 time.
✓ Branch 58 → 61 taken 122 times.
✓ Branch 59 → 60 taken 1 time.
|
123 | if (name == QLatin1String("mark") && value == QLatin1String("read")) return tr("Mark %n messages as read", nullptr, count); |
| 210 |
7/7✓ Branch 63 → 64 taken 29 times.
✓ Branch 63 → 68 taken 93 times.
✓ Branch 66 → 67 taken 1 time.
✓ Branch 66 → 68 taken 28 times.
✓ Branch 69 → 70 taken 1 time.
✓ Branch 69 → 72 taken 121 times.
✓ Branch 70 → 71 taken 1 time.
|
122 | if (name == QLatin1String("mark") && value == QLatin1String("unread")) return tr("Mark %n messages as unread", nullptr, count); |
| 211 |
6/6✓ Branch 74 → 75 taken 28 times.
✓ Branch 74 → 79 taken 93 times.
✓ Branch 77 → 78 taken 9 times.
✓ Branch 77 → 79 taken 19 times.
✓ Branch 80 → 81 taken 9 times.
✓ Branch 80 → 83 taken 112 times.
|
121 | if (name == QLatin1String("mark") && value == QLatin1String("important")) |
| 212 |
1/1✓ Branch 81 → 82 taken 9 times.
|
9 | return tr("Mark %n messages as important", nullptr, count); |
| 213 |
6/6✓ Branch 85 → 86 taken 19 times.
✓ Branch 85 → 90 taken 93 times.
✓ Branch 88 → 89 taken 9 times.
✓ Branch 88 → 90 taken 10 times.
✓ Branch 91 → 92 taken 9 times.
✓ Branch 91 → 94 taken 103 times.
|
112 | if (name == QLatin1String("mark") && value == QLatin1String("unimportant")) |
| 214 |
1/1✓ Branch 92 → 93 taken 9 times.
|
9 | return tr("Remove the important mark from %n messages", nullptr, count); |
| 215 |
3/3✓ Branch 96 → 97 taken 10 times.
✓ Branch 96 → 99 taken 93 times.
✓ Branch 97 → 98 taken 10 times.
|
103 | if (name == QLatin1String("mark")) return tr("Mark %n messages", nullptr, count); |
| 216 |
3/3✓ Branch 101 → 102 taken 20 times.
✓ Branch 101 → 104 taken 73 times.
✓ Branch 102 → 103 taken 20 times.
|
93 | if (name == QLatin1String("label")) return tr("Label %n messages", nullptr, count); |
| 217 |
3/3✓ Branch 106 → 107 taken 5 times.
✓ Branch 106 → 109 taken 68 times.
✓ Branch 107 → 108 taken 5 times.
|
73 | if (name == QLatin1String("unlabel")) return tr("Remove a label from %n messages", nullptr, count); |
| 218 | } | ||
| 219 |
5/6✓ Branch 111 → 112 taken 12 times.
✓ Branch 111 → 115 taken 2152 times.
✓ Branch 113 → 114 taken 12 times.
✗ Branch 113 → 115 not taken.
✓ Branch 116 → 117 taken 12 times.
✓ Branch 116 → 157 taken 2152 times.
|
2164 | if (name == QLatin1String("folder") && !folder.isEmpty()) { |
| 220 |
1/4✗ Branch 119 → 120 not taken.
✓ Branch 119 → 125 taken 12 times.
✗ Branch 120 → 121 not taken.
✗ Branch 122 → 123 not taken.
|
12 | if (value == QLatin1String("rename")) return tr("Rename “%1”").arg(folder); |
| 221 |
4/4✓ Branch 127 → 128 taken 3 times.
✓ Branch 127 → 133 taken 9 times.
✓ Branch 128 → 129 taken 3 times.
✓ Branch 130 → 131 taken 3 times.
|
15 | if (value == QLatin1String("delete")) return tr("Delete “%1” (asks first)").arg(folder); |
| 222 |
4/4✓ Branch 135 → 136 taken 4 times.
✓ Branch 135 → 141 taken 5 times.
✓ Branch 136 → 137 taken 4 times.
✓ Branch 138 → 139 taken 4 times.
|
13 | if (value == QLatin1String("move")) return tr("Move “%1” under another folder").arg(folder); |
| 223 |
1/4✗ Branch 143 → 144 not taken.
✓ Branch 143 → 149 taken 5 times.
✗ Branch 144 → 145 not taken.
✗ Branch 146 → 147 not taken.
|
5 | if (value == QLatin1String("new")) return tr("New folder inside “%1”").arg(folder); |
| 224 |
4/4✓ Branch 151 → 152 taken 1 time.
✓ Branch 151 → 157 taken 4 times.
✓ Branch 152 → 153 taken 1 time.
✓ Branch 154 → 155 taken 1 time.
|
6 | if (value == QLatin1String("properties")) return tr("Properties of “%1”").arg(folder); |
| 225 | } | ||
| 226 | 2156 | return {}; | |
| 227 | 2262 | } | |
| 228 | |||
| 229 | // Sprint 100 D-29: settings places — every page when nothing is typed, | ||
| 230 | // else places whose id starts with the text, the accounts | ||
| 231 | // ("accounts/<address>") and the catalog search (D-8), at most 12. | ||
| 232 | ✗ | QList<CommandCompletion::PlaceEntry> places(QuickMailBackend &backend, const QString &needle) { | |
| 233 | ✗ | QList<CommandCompletion::PlaceEntry> result; | |
| 234 | ✗ | QSet<QString> seen; | |
| 235 | ✗ | SettingsCatalog catalog; | |
| 236 | ✗ | const auto add = [&](const QString &place, const QString &label, const QString &path) { | |
| 237 | ✗ | if (place.isEmpty() || seen.contains(place) || result.size() >= 12) return; | |
| 238 | ✗ | seen.insert(place); | |
| 239 | ✗ | result.append({place, label, path}); | |
| 240 | ✗ | }; | |
| 241 | ✗ | const auto addPlace = [&](const QString &id) { | |
| 242 | ✗ | const QVariantMap place = catalog.place(id); | |
| 243 | ✗ | add(id, place.value(QStringLiteral("label")).toString(), place.value(QStringLiteral("path")).toString()); | |
| 244 | ✗ | }; | |
| 245 | ✗ | if (needle.isEmpty()) { | |
| 246 | ✗ | for (const auto &page : SettingsCatalog::pages()) addPlace(QString::fromLatin1(page.id)); | |
| 247 | ✗ | return result; | |
| 248 | } | ||
| 249 | ✗ | const auto starts = [&needle](const QString &id) { return id.startsWith(needle, Qt::CaseInsensitive); }; | |
| 250 | ✗ | for (const auto &page : SettingsCatalog::pages()) | |
| 251 | ✗ | if (starts(QString::fromLatin1(page.id))) addPlace(QString::fromLatin1(page.id)); | |
| 252 | ✗ | for (const auto &setting : SettingsCatalog::settings()) | |
| 253 | ✗ | if (starts(QString::fromLatin1(setting.id))) addPlace(QString::fromLatin1(setting.id)); | |
| 254 | ✗ | for (const auto &entry : backend.settings()->configuredAccounts()) { | |
| 255 | ✗ | const QString email = entry.toMap().value(QStringLiteral("email")).toString(); | |
| 256 | ✗ | const QString place = QStringLiteral("accounts/") + email; | |
| 257 | ✗ | if (starts(place) || email.contains(needle, Qt::CaseInsensitive)) add(place, email, catalog.label(QStringLiteral("accounts"))); | |
| 258 | ✗ | } | |
| 259 | ✗ | for (const auto &hit : SettingsCatalog::search(needle)) add(hit.place, hit.label, hit.path); | |
| 260 | ✗ | return result; | |
| 261 | ✗ | } | |
| 262 | |||
| 263 | ✗ | QList<CommandCompletion::AccountEntry> accounts(QuickMailBackend &backend) { | |
| 264 | ✗ | QList<CommandCompletion::AccountEntry> result; | |
| 265 | ✗ | const QString active = backend.activeAccountId(); | |
| 266 | ✗ | for (const auto &entry : backend.settings()->configuredAccounts()) { | |
| 267 | ✗ | const auto account = entry.toMap(); | |
| 268 | ✗ | result.append({account.value(QStringLiteral("email")).toString(), account.value(QStringLiteral("name")).toString(), | |
| 269 | ✗ | account.value(QStringLiteral("id")).toString() == active}); | |
| 270 | ✗ | } | |
| 271 | ✗ | return result; | |
| 272 | ✗ | } | |
| 273 | |||
| 274 | } // namespace CommandBarSourcesText | ||
| 275 | |||
| 276 | using namespace CommandBarSourcesText; | ||
| 277 | |||
| 278 | 765 | CommandCompletion::Sources commandBarSources(MailSessionCore &session, QuickMailBackend &backend, | |
| 279 | QuickCommandRouter &router) { | ||
| 280 | 765 | CommandCompletion::Sources sources; | |
| 281 | 3782 | sources.unavailableReason = [&backend](const QString &line) { return backend.namedCommandUnavailableReason(line); }; | |
| 282 | 854 | sources.folders = [&backend, &router](const QString &text, bool move) { return folders(backend, router, text, move); }; | |
| 283 | 795 | sources.labels = [&backend] { return labels(backend); }; | |
| 284 | 770 | sources.taskLists = [&session] { return taskLists(session); }; | |
| 285 | 765 | sources.tags = [&backend] { return tags(backend); }; | |
| 286 | 775 | sources.addresses = [&backend](const QString &prefix) { return addresses(backend, prefix); }; | |
| 287 | 966 | sources.results = [&backend](const QString &) { return results(backend); }; | |
| 288 | 3027 | sources.contextDetail = [&backend](const QString &line) { return contextDetail(backend, line); }; | |
| 289 | 765 | sources.places = [&backend](const QString &needle) { return places(backend, needle); }; | |
| 290 | 765 | sources.accounts = [&backend] { return accounts(backend); }; | |
| 291 | 1995 | sources.linePreview = [&backend](const QString &command, const QString &untrimmed) { | |
| 292 |
3/3✓ Branch 4 → 5 taken 26 times.
✓ Branch 4 → 7 taken 439 times.
✓ Branch 5 → 6 taken 26 times.
|
465 | if (command == QLatin1String("task")) return taskPreview(backend, untrimmed); |
| 293 |
1/1✓ Branch 7 → 8 taken 439 times.
|
439 | const QString line = untrimmed.trimmed(); |
| 294 |
3/3✓ Branch 10 → 11 taken 5 times.
✓ Branch 10 → 13 taken 434 times.
✓ Branch 11 → 12 taken 5 times.
|
439 | if (command == QLatin1String("event")) return eventPreview(backend, line); |
| 295 |
8/8✓ Branch 15 → 16 taken 203 times.
✓ Branch 15 → 20 taken 231 times.
✓ Branch 17 → 18 taken 203 times.
✓ Branch 18 → 19 taken 201 times.
✓ Branch 18 → 20 taken 2 times.
✓ Branch 21 → 22 taken 201 times.
✓ Branch 21 → 24 taken 233 times.
✓ Branch 22 → 23 taken 201 times.
|
434 | if (command == QLatin1String("search") && !line.startsWith(QLatin1String("in:"), Qt::CaseInsensitive)) return searchPreview(line); |
| 296 |
3/3✓ Branch 26 → 27 taken 16 times.
✓ Branch 26 → 29 taken 217 times.
✓ Branch 27 → 28 taken 16 times.
|
233 | if (command == QLatin1String("rule")) return rulePreview(backend, line); |
| 297 | 217 | return QVariantList{}; | |
| 298 | 1204 | }; | |
| 299 | 765 | return sources; | |
| 300 | } | ||
| 301 |