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.1% 16 / 0 / 17
Functions: 91.7% 11 / 0 / 12
Branches: 77.8% 14 / 0 / 18

presentation/WorkspacePersistence.h
Line Branch Exec Source
1 #pragma once
2 #include "UiStateStore.h"
3 #include "WorkspaceState.h"
4 #include "DesignTokens.h"
5 #include <QPointer>
6 #include <QThread>
7 #include <QTimer>
8
9 // P90.17: background writer for UI state. Lives on its own thread and owns
10 // the only writing UiStateStore, so QSaveFile commits, lock validation and
11 // JSON serialization never run on the GUI thread. Calls are serialized by
12 // the thread affinity; `write` returns its result for the blocking path.
13 class UiStateWriter final : public QObject {
14 Q_OBJECT
15 public:
16
1/1
✓ Branch 5 → 6 taken 776 times.
776 explicit UiStateWriter(QString directory) : m_store(std::move(directory)) {}
17 public slots:
18
1/1
✓ Branch 3 → 4 taken 776 times.
776 void initialize() { m_loaded = m_store.load(); }
19 607 bool write(quint64 generation, const QJsonObject &session, const QVariantMap &preferences) {
20 // S106-334: a load that failed once (the lock held by another
21 // instance for a moment) is tried again before the write, not left
22 // read-only for the whole session.
23
1/3
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 7 taken 607 times.
✗ Branch 4 → 5 not taken.
607 if (!m_loaded) m_loaded = m_store.load();
24
4/6
✓ Branch 7 → 8 taken 607 times.
✗ Branch 7 → 13 not taken.
✓ Branch 9 → 10 taken 606 times.
✓ Branch 9 → 13 taken 1 time.
✓ Branch 11 → 12 taken 606 times.
✗ Branch 11 → 13 not taken.
607 const bool ok = m_loaded && m_store.saveSession(session) && m_store.savePreferences(preferences);
25
3/3
✓ Branch 14 → 15 taken 606 times.
✓ Branch 14 → 16 taken 1 time.
✓ Branch 17 → 18 taken 607 times.
607 emit written(generation, ok, ok ? QString() : m_store.error());
26 607 return ok;
27 }
28 signals:
29 void written(quint64 generation, bool ok, const QString &error);
30 private:
31 UiStateStore m_store;
32 bool m_loaded = false;
33 };
34
35 // A host-owned, local-only persistence coordinator. Construct/load before QML;
36 // flush before destroying the workspace. It does not open a product profile.
37 //
38 // P90.17: debounced saves snapshot the small workspace state on the GUI
39 // thread and hand it to the background writer (latest-wins coalescing, at
40 // most one write in flight plus one replaced pending snapshot). flush()
41 // stays synchronous for the shutdown contract.
42 class WorkspacePersistence final : public QObject {
43 1 Q_OBJECT
44 public:
45 WorkspacePersistence(QString directory, WorkspaceState &workspace, DesignTokens &tokens,
46 QObject *parent = nullptr);
47 ~WorkspacePersistence() override;
48 bool load(const QString &legacyIniPath = {},
49 const std::function<bool(const MailId &)> &acceptIdentity = {});
50 bool flush();
51 ✗ QString error() const { return m_error; }
52 765 bool threaded() const { return m_threaded; }
53 // F95-15: the folder-suggestion column (Ctrl+S).
54 765 bool suggestions() const { return m_suggestions; }
55 void setSuggestions(bool on);
56 // Marks the preference dirty and schedules the debounced write.
57 void setThreaded(bool threaded);
58 // F3.2: whether the compose surface opens in its own top-level window.
59 765 bool composeWindowed() const { return m_composeWindowed; }
60 void setComposeWindowed(bool windowed);
61 // Q16: tray preference bridge (ui/closeToTray).
62 void restoreTray(class QuickTrayController *tray);
63 void setCloseToTray(bool on);
64 // Sprint 93 S93.3.9: the calendar's remembered state (keys viewMode,
65 // workWeek, hourZoom, hiddenCalendars, lastCalendar).
66 765 QVariantMap calendarState() const { return m_calendarState; }
67 void setCalendarState(const QVariantMap &state);
68 // Sprint 98 S98.1.6: CommandHistory::save() form ({history, recentFolders}).
69 765 QVariantMap commandBarState() const { return m_commandBarState; }
70 void setCommandBarState(const QVariantMap &state);
71 // Sprint 101 (D-26, D-30, D-22): {timelineCollapsed, timelineHintSeen, grouped}.
72 770 QVariantMap searchState() const { return m_searchState; }
73 void setSearchState(const QVariantMap &state);
74 signals:
75 void saveFailed(const QString &error);
76 // A snapshot write committed on the writer thread (durable).
77 void saved();
78 private:
79 void schedule();
80 struct Snapshot {
81 QJsonObject session;
82 QVariantMap preferences;
83 629 bool operator==(const Snapshot &other) const {
84
4/4
✓ Branch 3 → 4 taken 100 times.
✓ Branch 3 → 7 taken 529 times.
✓ Branch 5 → 6 taken 11 times.
✓ Branch 5 → 7 taken 89 times.
629 return session == other.session && preferences == other.preferences;
85 }
86 };
87 Snapshot buildSnapshot() const;
88 void flushAsync();
89 void dispatchPendingWrite();
90 UiStateStore m_store;
91 WorkspaceState &m_workspace;
92 DesignTokens &m_tokens;
93 QTimer m_timer;
94 QString m_error;
95 bool m_loaded = false;
96 bool m_dirty = false;
97 bool m_threaded = false;
98 bool m_suggestions = false;
99 bool m_composeWindowed = false;
100 bool m_closeToTray = true;
101 QVariantMap m_calendarState;
102 QVariantMap m_commandBarState;
103 QVariantMap m_searchState;
104 QPointer<class QuickTrayController> m_tray;
105 QThread m_writerThread;
106 QPointer<UiStateWriter> m_writer;
107 Snapshot m_pendingSnapshot, m_lastDispatched;
108 quint64 m_writeGeneration = 0;
109 bool m_writeInFlight = false;
110 bool m_pendingWrite = false;
111 };
112