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: 50.0% 1 / 0 / 2
Functions: 50.0% 1 / 0 / 2
Branches: -% 0 / 0 / 0

ui/MailThreadModel.h
Line Branch Exec Source
1 #pragma once
2
3 #include <QAbstractItemModel>
4 #include <QList>
5 #include <QMimeData>
6 #include <QPair>
7 #include <memory>
8 #include <vector>
9
10 #include "controller/ThreadBuilder.h"
11 #include "data/Models.h"
12
13 // MailThreadModel: Hierarchical tree model for threaded mail display.
14 // Wraps ThreadBuilder output into a QAbstractItemModel for QTreeView.
15 class MailThreadModel : public QAbstractItemModel {
16 ✗ Q_OBJECT
17
18 public:
19 // T-514: Composite identity key (folderId, uid)
20 using MailKey = QPair<qint64, qint64>;
21 struct VisibleRow { ThreadNode *source = nullptr; int depth = 0; };
22 struct PreparedThreads {
23 std::vector<std::unique_ptr<ThreadNode>> roots;
24 QHash<MailKey, ThreadNode *> uidIndex;
25 QVector<VisibleRow> rows;
26 QHash<MailKey, int> rowByKey;
27 qint64 retainedBytes = 0;
28 };
29 using Prepared = std::shared_ptr<PreparedThreads>;
30 // Pure data only: prepare indexing, counters and the default visible order
31 // in the same worker as ThreadBuilder, without constructing QModelIndexes.
32 static Prepared prepareRoots(std::vector<std::unique_ptr<ThreadNode>> roots);
33 void setPrepared(Prepared prepared);
34 3414 Prepared prepared() const { return m_prepared; }
35 enum Column { Star = 0, Attachment, Subject, Suggestion, From, Date, Size, ColumnCount };
36 enum CustomRoles {
37 SortRole = Qt::UserRole,
38 FlagsRole = Qt::UserRole + 1,
39 HasAttachmentsRole = Qt::UserRole + 2,
40 LabelsRole = Qt::UserRole + 3,
41 ThreadCountRole = Qt::UserRole + 4,
42 DepthRole = Qt::UserRole + 5 // T-128
43 };
44
45 explicit MailThreadModel(QObject *parent = nullptr);
46 ~MailThreadModel() override;
47
48 // Set complete header list (rebuilds thread tree)
49 void setHeaders(const QList<MailHeader> &headers);
50
51 // F3.12: adopt an already-built forest (constructed off the GUI thread) and
52 // publish it with one model reset. Ownership transfers to the model.
53 void setBuiltRoots(std::vector<std::unique_ptr<ThreadNode>> roots);
54
55 // Append new headers (rebuilds thread tree)
56 void appendHeaders(const QList<MailHeader> &headers);
57
58 // Clear all data
59 void clear();
60
61 // Access helpers
62 const MailHeader *headerAt(const QModelIndex &index) const;
63 qint64 uidAt(const QModelIndex &index) const;
64 QModelIndex indexForUid(qint64 uid, qint64 folderId) const;
65
66 // Update a specific header's flags
67 // T-514: folderId required for composite key lookup.
68 void updateFlags(qint64 uid, quint32 flags, qint64 folderId);
69
70 // T-261: Update a specific header's labels and emit dataChanged
71 // T-514: folderId required for composite key lookup.
72 void updateLabels(qint64 uid, const QStringList &labels, qint64 folderId);
73
74 // Remove a mail by UID (rebuilds thread tree)
75 // T-514: folderId required for composite key lookup.
76 void removeByUid(qint64 uid, qint64 folderId);
77
78 // T-232: Suggestion column cache
79 // T-514: folderId required for composite key lookup.
80 void setSuggestion(qint64 uid, qint64 folderId, const QString &text, double confidence);
81 void clearSuggestions();
82
83 // QAbstractItemModel interface
84 QModelIndex index(int row, int column,
85 const QModelIndex &parent = {}) const override;
86 QModelIndex parent(const QModelIndex &child) const override;
87 int rowCount(const QModelIndex &parent = {}) const override;
88 int columnCount(const QModelIndex &parent = {}) const override;
89 QVariant data(const QModelIndex &index,
90 int role = Qt::DisplayRole) const override;
91 QVariant headerData(int section, Qt::Orientation orientation,
92 int role = Qt::DisplayRole) const override;
93
94 // Sprint 76 (T-76.B3): refresh translated headers on a live language switch.
95 void retranslateUi();
96
97 // T-102: Drag & Drop support
98 Qt::ItemFlags flags(const QModelIndex &index) const override;
99 QStringList mimeTypes() const override;
100 QMimeData *mimeData(const QModelIndexList &indexes) const override;
101 Qt::DropActions supportedDragActions() const override;
102
103 private:
104 ThreadNode *nodeFromIndex(const QModelIndex &index) const;
105 QModelIndex indexFromNode(ThreadNode *node, int column = 0) const;
106 QList<MailHeader> snapshotHeaders(const ThreadNode *excluded = nullptr) const;
107
108 Prepared m_prepared;
109
110 // T-232: Suggestion cache ((folderId,UID) → {text, confidence})
111 struct SuggestionEntry { QString text; double confidence; };
112 QHash<MailKey, SuggestionEntry> m_suggestionCache;
113 };
114