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: 94.6% 176 / 0 / 186
Functions: 89.2% 33 / 0 / 37
Branches: 81.4% 228 / 0 / 280

presentation/MailSearchSessions.cpp
Line Branch Exec Source
1 #include "MailSearchSessions.h"
2
3 #include "app/SearchMatch.h"
4
5 #include "SearchLog.h"
6 #include "WorkspaceState.h"
7 #include "controller/MailController.h"
8 #include "controller/ServerSearchSession.h"
9
10
1/1
✓ Branch 9 → 10 taken 795 times.
795 MailSearchSessions::MailSearchSessions(Deps deps, QObject *parent) : QObject(parent), m_deps(std::move(deps)) {
11 795 auto *workspace = m_deps.workspace;
12
1/1
✓ Branch 10 → 11 taken 795 times.
795 connect(workspace, &WorkspaceState::activeTabChanged, this, &MailSearchSessions::syncActive);
13
1/1
✓ Branch 12 → 13 taken 795 times.
795 connect(workspace, &WorkspaceState::areaChanged, this, &MailSearchSessions::syncActive);
14
1/1
✓ Branch 14 → 15 taken 795 times.
795 connect(workspace, &WorkspaceState::modelReset, this, &MailSearchSessions::syncActive);
15
1/1
✓ Branch 16 → 17 taken 795 times.
795 connect(workspace, &WorkspaceState::tabRemoved, this, [this](const QString &tabId, const QString &kind) {
16
2/2
✓ Branch 4 → 5 taken 62 times.
✓ Branch 4 → 6 taken 13 times.
75 if (kind != QLatin1String("search")) return;
17 13 m_recent.removeAll(tabId);
18
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 13 times.
13 if (m_activeTabId == tabId) m_activeTabId.clear();
19 13 m_matchWords.erase(tabId);
20 13 m_sessions.erase(tabId); // its destructor cancels its reads and server search
21 13 emit activeChanged();
22 });
23
1/1
✓ Branch 18 → 19 taken 795 times.
795 connect(workspace, &WorkspaceState::selectionChanged, this, [this] {
24
1/1
✓ Branch 2 → 3 taken 1569 times.
1569 MailSearchSession *session = active();
25
2/2
✓ Branch 3 → 4 taken 1351 times.
✓ Branch 3 → 5 taken 218 times.
1569 if (!session) return;
26 218 const MailId selected = m_deps.workspace->mailId();
27
1/1
✓ Branch 7 → 8 taken 218 times.
218 session->setSelected(selected);
28
3/3
✓ Branch 9 → 10 taken 118 times.
✓ Branch 9 → 14 taken 100 times.
✓ Branch 11 → 12 taken 118 times.
218 if (selected.isValid()) m_deps.workspace->setSearchAnchor(session->tabId(), selected);
29 218 });
30
1/1
✓ Branch 20 → 21 taken 795 times.
935 connect(this, &MailSearchSessions::activeChanged, this, [this] { m_timeline.setSession(active()); });
31
1/1
✓ Branch 22 → 23 taken 795 times.
812 connect(&m_timeline, &SearchTimelineModel::rangeApplied, this, [this] { setTimelineHintSeen(true); });
32
1/1
✓ Branch 24 → 25 taken 795 times.
795 connect(&m_timeline, &SearchTimelineModel::timelineChanged, this, &MailSearchSessions::updatePeriods);
33
1/1
✓ Branch 26 → 27 taken 795 times.
795 connect(this, &MailSearchSessions::activeChanged, this, &MailSearchSessions::updatePeriods);
34
1/1
✓ Branch 28 → 29 taken 795 times.
795 wireController();
35
1/1
✓ Branch 29 → 30 taken 795 times.
795 syncActive();
36 795 }
37
38 1590 MailSearchSessions::~MailSearchSessions() = default;
39
40 795 void MailSearchSessions::wireController() {
41
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 795 times.
795 if (!m_deps.controller) return;
42 795 ServerSearchSession *server = m_deps.controller->search();
43 795 connect(server, &ServerSearchSession::serverSearchResultReceived, this,
44
1/1
✓ Branch 5 → 6 taken 795 times.
795 [this](const QList<qint64> &uids, qint64 folderId, const QString &path) {
45
1/2
✓ Branch 3 → 4 taken 5 times.
✗ Branch 3 → 5 not taken.
5 if (MailSearchSession *owner = serverOwner()) owner->serverHits(uids, folderId, path);
46 5 });
47
1/1
✓ Branch 7 → 8 taken 795 times.
795 connect(server, &ServerSearchSession::serverSearchProgress, this, [this](int done, int total) {
48 ✗ if (MailSearchSession *owner = serverOwner()) owner->serverProgress(done, total);
49 ✗ });
50
1/1
✓ Branch 9 → 10 taken 795 times.
795 connect(server, &ServerSearchSession::serverSearchFolderFailed, this, [this](const QString &) {
51 ✗ if (MailSearchSession *owner = serverOwner()) owner->serverFolderFailed();
52 ✗ });
53
1/1
✓ Branch 11 → 12 taken 795 times.
795 connect(server, &ServerSearchSession::serverSearchComplete, this, [this] {
54 ✗ if (MailSearchSession *owner = serverOwner()) owner->serverFinished();
55 ✗ });
56
1/1
✓ Branch 13 → 14 taken 795 times.
795 connect(m_deps.controller, &MailController::movesVisuallyPending, this, &MailSearchSessions::onMovesPending);
57
1/1
✓ Branch 15 → 16 taken 795 times.
795 connect(m_deps.controller, &MailController::seenVisualChanged, this, [this](qint64 folderId, qint64 uid, bool seen) {
58
3/3
✓ Branch 8 → 9 taken 4 times.
✓ Branch 11 → 4 taken 4 times.
✓ Branch 11 → 12 taken 73 times.
77 for (auto &[id, session] : m_sessions) session->setFlag(folderId, uid, MailFlag::Seen, seen);
59 73 });
60
1/1
✓ Branch 17 → 18 taken 795 times.
795 connect(m_deps.controller, &MailController::starVisualChanged, this, [this](qint64 folderId, qint64 uid, bool starred) {
61
3/3
✓ Branch 8 → 9 taken 242 times.
✓ Branch 11 → 4 taken 242 times.
✓ Branch 11 → 12 taken 298 times.
540 for (auto &[id, session] : m_sessions) session->setFlag(folderId, uid, MailFlag::Flagged, starred);
62 298 });
63 }
64
65 5 MailSearchSession *MailSearchSessions::serverOwner() const {
66
3/7
✓ Branch 2 → 3 taken 5 times.
✗ Branch 2 → 7 not taken.
✓ Branch 5 → 6 taken 5 times.
✓ Branch 9 → 10 taken 5 times.
✗ Branch 9 → 11 not taken.
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 15 not taken.
5 return m_deps.controller ? session(m_deps.controller->search()->owner()) : nullptr;
67 }
68
69 5056 MailSearchSession *MailSearchSessions::session(const QString &tabId) const {
70
1/1
✓ Branch 2 → 3 taken 5056 times.
5056 const auto it = m_sessions.find(tabId);
71
2/2
✓ Branch 5 → 6 taken 2073 times.
✓ Branch 5 → 7 taken 2983 times.
5056 return it == m_sessions.end() ? nullptr : it->second.get();
72 }
73
74 4845 MailSearchSession *MailSearchSessions::active() const { return session(m_activeTabId); }
75
76 310 bool MailSearchSessions::activeDormant() const {
77 310 const int row = m_deps.workspace->rowForTabId(m_activeTabId);
78
4/4
✓ Branch 3 → 4 taken 220 times.
✓ Branch 3 → 7 taken 90 times.
✓ Branch 5 → 6 taken 12 times.
✓ Branch 5 → 7 taken 208 times.
310 return row >= 0 && m_deps.workspace->tabDormant(row);
79 }
80
81 2 QString MailSearchSessions::activeAccount() const { return m_deps.workspace->searchAccount(m_activeTabId); }
82
83 2 int MailSearchSessions::liveCount() const {
84 2 int live = 0;
85
4/4
✓ Branch 9 → 10 taken 6 times.
✓ Branch 9 → 11 taken 2 times.
✓ Branch 14 → 4 taken 8 times.
✓ Branch 14 → 15 taken 2 times.
10 for (const auto &[id, session] : m_sessions) live += session->live() ? 1 : 0;
86 2 return live;
87 }
88
89 769 void MailSearchSessions::setTimelineShown(bool shown) {
90
2/2
✓ Branch 2 → 3 taken 765 times.
✓ Branch 2 → 4 taken 4 times.
769 if (m_timelineShown == shown) return;
91 4 m_timelineShown = shown;
92
6/6
✓ Branch 4 → 5 taken 4 times.
✓ Branch 8 → 9 taken 4 times.
✓ Branch 9 → 10 taken 4 times.
✓ Branch 10 → 11 taken 4 times.
✓ Branch 14 → 6 taken 4 times.
✓ Branch 14 → 15 taken 4 times.
8 qCInfo(lcSearch) << "Search tabs: timeline shown" << shown;
93 4 emit timelineShownChanged();
94 }
95
96 767 void MailSearchSessions::setGrouped(bool on) {
97
2/2
✓ Branch 2 → 3 taken 765 times.
✓ Branch 2 → 4 taken 2 times.
767 if (m_grouped == on) return;
98 2 m_grouped = on;
99
6/6
✓ Branch 4 → 5 taken 2 times.
✓ Branch 8 → 9 taken 2 times.
✓ Branch 9 → 10 taken 2 times.
✓ Branch 10 → 11 taken 2 times.
✓ Branch 14 → 6 taken 2 times.
✓ Branch 14 → 15 taken 2 times.
4 qCInfo(lcSearch) << "Search tabs: grouped by period" << on;
100 2 updatePeriods();
101 2 emit groupedChanged();
102 }
103
104 140 void MailSearchSessions::updateMatchWords(MailSearchSession *session) {
105
1/1
✓ Branch 3 → 4 taken 140 times.
140 const auto words = m_matchWords.find(session->tabId());
106
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 140 times.
140 if (words == m_matchWords.end()) return;
107 // No dataChanged here: a new query always replaces the rows, which
108 // re-reads the role.
109
1/1
✓ Branch 10 → 11 taken 140 times.
140 *words->second = SearchMatch::words(session->query());
110 }
111
112 10967 QString MailSearchSessions::markMatches(const QString &text, const QString &open, const QString &close) const {
113
1/1
✓ Branch 2 → 3 taken 10967 times.
10967 const auto words = m_matchWords.find(m_activeTabId);
114
2/3
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 10967 times.
✓ Branch 10 → 11 taken 10967 times.
10967 return SearchMatch::markup(text, words == m_matchWords.end() ? QStringList() : *words->second, open, close);
115 }
116
117 808 void MailSearchSessions::updatePeriods() {
118
2/2
✓ Branch 3 → 4 taken 745 times.
✓ Branch 3 → 13 taken 63 times.
808 if (MailSearchSession *session = active())
119
6/7
✓ Branch 4 → 5 taken 2 times.
✓ Branch 4 → 9 taken 743 times.
✓ Branch 5 → 6 taken 2 times.
✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 9 not taken.
✓ Branch 7 → 8 taken 2 times.
✓ Branch 10 → 11 taken 745 times.
747 session->setPeriodUnit(m_grouped && m_timeline.hasData() ? m_timeline.unitName() : QString());
120 808 }
121
122 2 void MailSearchSessions::setAllFolders(bool on) {
123
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 2 times.
2 if (m_allFolders == on) return;
124 2 m_allFolders = on;
125
6/6
✓ Branch 4 → 5 taken 2 times.
✓ Branch 8 → 9 taken 2 times.
✓ Branch 9 → 10 taken 2 times.
✓ Branch 10 → 11 taken 2 times.
✓ Branch 14 → 6 taken 2 times.
✓ Branch 14 → 15 taken 2 times.
4 qCInfo(lcSearch) << "Search tabs: sidebar shows all folders" << on;
126 2 emit allFoldersChanged();
127 }
128
129 782 void MailSearchSessions::setTimelineHintSeen(bool seen) {
130
2/2
✓ Branch 2 → 3 taken 775 times.
✓ Branch 2 → 4 taken 7 times.
782 if (m_timelineHintSeen == seen) return;
131 7 m_timelineHintSeen = seen;
132 7 emit timelineHintSeenChanged();
133 }
134
135 102 MailSearchSession *MailSearchSessions::ensure(const QString &tabId) {
136
3/3
✓ Branch 2 → 3 taken 102 times.
✓ Branch 3 → 4 taken 13 times.
✓ Branch 3 → 5 taken 89 times.
102 if (MailSearchSession *existing = session(tabId)) return existing;
137
1/1
✓ Branch 5 → 6 taken 89 times.
89 const QString account = m_deps.workspace->searchAccount(tabId);
138
3/6
✓ Branch 7 → 8 taken 89 times.
✗ Branch 7 → 10 not taken.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 89 times.
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 89 times.
89 if (account.isEmpty() || !m_deps.sessionDeps) return nullptr;
139
2/2
✓ Branch 14 → 15 taken 89 times.
✓ Branch 15 → 16 taken 89 times.
89 auto created = std::make_unique<MailSearchSession>(tabId, account, m_deps.sessionDeps(account));
140 89 MailSearchSession *raw = created.get();
141
1/1
✓ Branch 18 → 19 taken 89 times.
89 connect(raw, &MailSearchSession::queryChanged, this, [this, raw] {
142
2/2
✓ Branch 3 → 4 taken 140 times.
✓ Branch 6 → 7 taken 140 times.
140 m_deps.workspace->setSearchQuery(raw->tabId(), raw->query(), raw->title(), raw->query());
143 140 updateMatchWords(raw);
144 140 });
145 // S101.1.10: a row whose words are in none of subject, sender and
146 // recipients matched in its text.
147
2/2
✓ Branch 21 → 22 taken 89 times.
✓ Branch 22 → 23 taken 89 times.
89 auto words = std::make_shared<QStringList>(SearchMatch::words(raw->query()));
148
1/1
✓ Branch 25 → 26 taken 89 times.
89 m_matchWords[tabId] = words;
149
2/2
✓ Branch 29 → 30 taken 89 times.
✓ Branch 30 → 31 taken 89 times.
89 raw->resultModel()->setMatchProvider([words](const MailHeader &header) {
150
2/2
✓ Branch 7 → 8 taken 98 times.
✓ Branch 7 → 18 taken 9972 times.
22143 return !words->isEmpty() && !SearchMatch::matches(header.subject, *words) &&
151
5/6
✓ Branch 4 → 5 taken 10070 times.
✓ Branch 4 → 18 taken 2003 times.
✓ Branch 10 → 11 taken 36 times.
✓ Branch 10 → 18 taken 62 times.
✓ Branch 13 → 14 taken 36 times.
✗ Branch 13 → 18 not taken.
22179 !SearchMatch::matches(header.from, *words) && !SearchMatch::matches(header.to, *words) &&
152
1/2
✓ Branch 16 → 17 taken 36 times.
✗ Branch 16 → 18 not taken.
12109 !SearchMatch::matches(header.cc, *words);
153 });
154 89 connect(raw, &MailSearchSession::rowsReplaced, this,
155
1/1
✓ Branch 33 → 34 taken 89 times.
210 [this, raw](const MailId &selected) { onRowsReplaced(raw, selected); });
156
1/1
✓ Branch 36 → 37 taken 89 times.
89 m_sessions.emplace(tabId, std::move(created));
157
6/6
✓ Branch 37 → 38 taken 89 times.
✓ Branch 41 → 42 taken 89 times.
✓ Branch 42 → 43 taken 89 times.
✓ Branch 44 → 45 taken 89 times.
✓ Branch 48 → 39 taken 89 times.
✓ Branch 48 → 49 taken 89 times.
178 qCInfo(lcSearch) << "Search tabs: session created, sessions" << m_sessions.size();
158 89 return raw;
159 89 }
160
161 102 void MailSearchSessions::touch(const QString &tabId) {
162 102 m_recent.removeAll(tabId);
163 102 m_recent.prepend(tabId);
164 // D-3: the active session and the two most recently used keep their rows.
165
2/2
✓ Branch 11 → 5 taken 7 times.
✓ Branch 11 → 12 taken 102 times.
109 for (int i = MaximumLiveSessions; i < m_recent.size(); ++i)
166
1/2
✓ Branch 7 → 8 taken 7 times.
✗ Branch 7 → 9 not taken.
7 if (MailSearchSession *old = session(m_recent.at(i))) old->release();
167 102 }
168
169 2075 void MailSearchSessions::syncActive() {
170 2075 auto *workspace = m_deps.workspace;
171
5/6
✓ Branch 5 → 6 taken 1591 times.
✓ Branch 5 → 9 taken 484 times.
✓ Branch 7 → 8 taken 199 times.
✓ Branch 7 → 9 taken 1392 times.
✓ Branch 10 → 11 taken 2075 times.
✗ Branch 10 → 12 not taken.
2075 const bool searchShown = workspace->area() == QLatin1String("mail") && workspace->activeIsSearch();
172
2/2
✓ Branch 12 → 13 taken 199 times.
✓ Branch 12 → 14 taken 1876 times.
2075 const QString tabId = searchShown ? workspace->activeTabId() : QString();
173
8/9
✓ Branch 16 → 17 taken 1948 times.
✓ Branch 16 → 22 taken 127 times.
✓ Branch 18 → 19 taken 97 times.
✓ Branch 18 → 21 taken 1851 times.
✓ Branch 19 → 20 taken 97 times.
✓ Branch 20 → 21 taken 97 times.
✗ Branch 20 → 22 not taken.
✓ Branch 23 → 24 taken 1948 times.
✓ Branch 23 → 25 taken 127 times.
2075 if (tabId == m_activeTabId && (tabId.isEmpty() || session(tabId))) return;
174
4/4
✓ Branch 25 → 26 taken 127 times.
✓ Branch 26 → 27 taken 39 times.
✓ Branch 26 → 28 taken 88 times.
✓ Branch 27 → 28 taken 39 times.
127 if (MailSearchSession *previous = active()) previous->deactivate();
175 127 m_activeTabId = tabId;
176
3/3
✓ Branch 30 → 31 taken 25 times.
✓ Branch 30 → 32 taken 102 times.
✓ Branch 32 → 33 taken 102 times.
127 MailSearchSession *current = tabId.isEmpty() ? nullptr : ensure(tabId);
177
2/2
✓ Branch 34 → 35 taken 102 times.
✓ Branch 34 → 60 taken 25 times.
127 if (current) {
178
1/1
✓ Branch 35 → 36 taken 102 times.
102 touch(tabId);
179
3/3
✓ Branch 36 → 37 taken 102 times.
✓ Branch 37 → 38 taken 100 times.
✓ Branch 37 → 60 taken 2 times.
102 if (!activeDormant()) {
180
4/6
✓ Branch 40 → 41 taken 89 times.
✓ Branch 40 → 44 taken 11 times.
✓ Branch 42 → 43 taken 89 times.
✗ Branch 42 → 44 not taken.
✓ Branch 45 → 46 taken 100 times.
✗ Branch 45 → 47 not taken.
100 const bool fresh = current->query().isEmpty() && current->stateValue() == MailSearchSession::State::Empty;
181
1/1
✓ Branch 47 → 48 taken 100 times.
100 const QString stored = workspace->searchQuery(tabId);
182
1/1
✓ Branch 48 → 49 taken 100 times.
100 current->activate();
183
7/7
✓ Branch 49 → 50 taken 89 times.
✓ Branch 49 → 53 taken 11 times.
✓ Branch 51 → 52 taken 85 times.
✓ Branch 51 → 53 taken 4 times.
✓ Branch 54 → 55 taken 85 times.
✓ Branch 54 → 56 taken 15 times.
✓ Branch 55 → 56 taken 85 times.
100 if (fresh && !stored.isEmpty()) current->setQuery(stored); // a restored tab re-runs now (D-16)
184
1/1
✓ Branch 57 → 58 taken 100 times.
100 current->setSelected(workspace->mailId());
185 100 }
186 }
187
1/1
✓ Branch 60 → 61 taken 127 times.
127 emit activeChanged();
188 2075 }
189
190 93 bool MailSearchSessions::open(const QString &query, bool newTab) {
191
2/3
✓ Branch 3 → 4 taken 93 times.
✗ Branch 3 → 5 not taken.
✓ Branch 4 → 6 taken 93 times.
93 const QString account = m_deps.currentAccount ? m_deps.currentAccount() : QString();
192
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 93 times.
93 if (account.isEmpty()) return false;
193
1/1
✓ Branch 9 → 10 taken 93 times.
93 const QString canonical = SearchTermModel::canonical(query);
194
1/1
✓ Branch 14 → 15 taken 93 times.
93 const int row = m_deps.workspace->openSearch(canonical, account,
195
1/1
✓ Branch 10 → 11 taken 93 times.
186 SearchTermModel::title(canonical), newTab);
196
1/2
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 93 times.
93 if (row < 0) return false;
197
1/1
✓ Branch 23 → 24 taken 93 times.
186 m_deps.workspace->setArea(QStringLiteral("mail"));
198
1/1
✓ Branch 26 → 27 taken 93 times.
93 syncActive();
199
1/1
✓ Branch 27 → 28 taken 93 times.
93 MailSearchSession *session = active();
200
1/2
✗ Branch 28 → 29 not taken.
✓ Branch 28 → 30 taken 93 times.
93 if (!session) return false;
201
1/1
✓ Branch 30 → 31 taken 93 times.
93 session->setQuery(canonical);
202
9/9
✓ Branch 31 → 32 taken 93 times.
✓ Branch 35 → 36 taken 93 times.
✓ Branch 36 → 37 taken 93 times.
✓ Branch 37 → 38 taken 93 times.
✓ Branch 38 → 39 taken 93 times.
✓ Branch 39 → 40 taken 93 times.
✓ Branch 41 → 42 taken 93 times.
✓ Branch 46 → 33 taken 93 times.
✓ Branch 46 → 47 taken 93 times.
186 qCInfo(lcSearch) << "Search tab opened, new tab" << newTab << "tabs" << m_deps.workspace->searchTabIds().size();
203 93 return true;
204 186 }
205
206 ✗ void MailSearchSessions::refreshAfterIndexReady() {
207 ✗ for (auto &[id, session] : m_sessions)
208 ✗ if (session->live()) session->refreshAfterIndexReady();
209 ✗ }
210
211 99 void MailSearchSessions::selectRow(MailSearchSession *session, int row) {
212
6/10
✓ Branch 2 → 3 taken 99 times.
✓ Branch 3 → 4 taken 99 times.
✗ Branch 3 → 7 not taken.
✓ Branch 4 → 5 taken 99 times.
✗ Branch 4 → 7 not taken.
✓ Branch 5 → 6 taken 99 times.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 99 times.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 99 times.
99 if (session != active() || row < 0 || row >= session->loadedCount()) return;
213
1/1
✓ Branch 11 → 12 taken 99 times.
99 const MailId mail = session->mailIdAt(row);
214
5/9
✓ Branch 13 → 14 taken 99 times.
✗ Branch 13 → 18 not taken.
✓ Branch 15 → 16 taken 99 times.
✗ Branch 15 → 19 not taken.
✓ Branch 16 → 17 taken 99 times.
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 19 taken 99 times.
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 99 times.
99 if (!mail.isValid() || (m_deps.acceptIdentity && !m_deps.acceptIdentity(mail))) return;
215
1/1
✓ Branch 22 → 23 taken 99 times.
99 m_deps.workspace->select(mail);
216
1/1
✓ Branch 23 → 24 taken 99 times.
99 emit selectionRevealRequested(row);
217 99 }
218
219 // D-29: a re-run keeps the selected result when it still matches; otherwise
220 // the first result becomes the selection (the reader is never blank while
221 // there are results, PT-08).
222 121 void MailSearchSessions::onRowsReplaced(MailSearchSession *session, const MailId &selected) {
223
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 120 times.
121 if (session != active()) return;
224
2/2
✓ Branch 6 → 7 taken 12 times.
✓ Branch 6 → 10 taken 108 times.
120 if (selected.isValid()) {
225 12 emit selectionRevealRequested(session->rowOf(selected));
226 12 return;
227 }
228
2/2
✓ Branch 11 → 12 taken 99 times.
✓ Branch 11 → 13 taken 9 times.
108 if (session->loadedCount() > 0) selectRow(session, 0);
229
1/1
✓ Branch 13 → 14 taken 9 times.
9 else m_deps.workspace->select({});
230 }
231
232 // A move (archive, delete, junk, move) takes results out of every search;
233 // the active tab selects the result that followed the moved one.
234 47 void MailSearchSessions::onMovesPending(qint64 folderId, const QList<qint64> &uids) {
235
1/1
✓ Branch 2 → 3 taken 47 times.
47 MailSearchSession *current = active();
236 47 const MailId selected = m_deps.workspace->mailId();
237
4/6
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 10 taken 46 times.
✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 10 not taken.
✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 10 not taken.
47 const bool selectedMoves = current && selected.folderId == folderId && uids.contains(selected.uid);
238
3/3
✓ Branch 11 → 12 taken 1 time.
✓ Branch 11 → 14 taken 46 times.
✓ Branch 12 → 13 taken 1 time.
47 const int row = selectedMoves ? current->rowOf(selected) : -1;
239
3/3
✓ Branch 21 → 22 taken 1 time.
✓ Branch 24 → 17 taken 1 time.
✓ Branch 24 → 25 taken 47 times.
48 for (auto &[id, session] : m_sessions) session->removeRows(folderId, uids);
240
2/2
✓ Branch 25 → 26 taken 46 times.
✓ Branch 25 → 27 taken 1 time.
47 if (!selectedMoves) return;
241
3/9
✓ Branch 27 → 28 taken 1 time.
✗ Branch 28 → 29 not taken.
✓ Branch 28 → 31 taken 1 time.
✗ Branch 29 → 30 not taken.
✗ Branch 29 → 31 not taken.
✗ Branch 32 → 33 not taken.
✓ Branch 32 → 37 taken 1 time.
✗ Branch 33 → 34 not taken.
✗ Branch 35 → 36 not taken.
1 if (current->loadedCount() > 0 && row >= 0) selectRow(current, qMin(row, current->loadedCount() - 1));
242
1/1
✓ Branch 37 → 38 taken 1 time.
1 else m_deps.workspace->select({});
243 47 }
244