Line data Source code
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 331 : Q_OBJECT
17 :
18 : public:
19 : // T-514: Composite identity key (folderId, uid)
20 : using MailKey = QPair<qint64, qint64>;
21 : enum Column { Star = 0, Attachment, Subject, Suggestion, From, Date, Size, ColumnCount };
22 : enum CustomRoles {
23 : SortRole = Qt::UserRole,
24 : FlagsRole = Qt::UserRole + 1,
25 : HasAttachmentsRole = Qt::UserRole + 2,
26 : LabelsRole = Qt::UserRole + 3,
27 : ThreadCountRole = Qt::UserRole + 4,
28 : DepthRole = Qt::UserRole + 5 // T-128
29 : };
30 :
31 : explicit MailThreadModel(QObject *parent = nullptr);
32 : ~MailThreadModel() override;
33 :
34 : // Set complete header list (rebuilds thread tree)
35 : void setHeaders(const QList<MailHeader> &headers);
36 :
37 : // Append new headers (rebuilds thread tree)
38 : void appendHeaders(const QList<MailHeader> &headers);
39 :
40 : // Clear all data
41 : void clear();
42 :
43 : // Access helpers
44 : const MailHeader *headerAt(const QModelIndex &index) const;
45 : qint64 uidAt(const QModelIndex &index) const;
46 : QModelIndex indexForUid(qint64 uid, qint64 folderId) const;
47 :
48 : // Update a specific header's flags
49 : // T-514: folderId required for composite key lookup.
50 : void updateFlags(qint64 uid, quint32 flags, qint64 folderId);
51 :
52 : // T-261: Update a specific header's labels and emit dataChanged
53 : // T-514: folderId required for composite key lookup.
54 : void updateLabels(qint64 uid, const QStringList &labels, qint64 folderId);
55 :
56 : // Remove a mail by UID (rebuilds thread tree)
57 : // T-514: folderId required for composite key lookup.
58 : void removeByUid(qint64 uid, qint64 folderId);
59 :
60 : // T-232: Suggestion column cache
61 : // T-514: folderId required for composite key lookup.
62 : void setSuggestion(qint64 uid, qint64 folderId, const QString &text, double confidence);
63 : void clearSuggestions();
64 :
65 : // QAbstractItemModel interface
66 : QModelIndex index(int row, int column,
67 : const QModelIndex &parent = {}) const override;
68 : QModelIndex parent(const QModelIndex &child) const override;
69 : int rowCount(const QModelIndex &parent = {}) const override;
70 : int columnCount(const QModelIndex &parent = {}) const override;
71 : QVariant data(const QModelIndex &index,
72 : int role = Qt::DisplayRole) const override;
73 : QVariant headerData(int section, Qt::Orientation orientation,
74 : int role = Qt::DisplayRole) const override;
75 :
76 : // Sprint 76 (T-76.B3): refresh translated headers on a live language switch.
77 : void retranslateUi();
78 :
79 : // T-102: Drag & Drop support
80 : Qt::ItemFlags flags(const QModelIndex &index) const override;
81 : QStringList mimeTypes() const override;
82 : QMimeData *mimeData(const QModelIndexList &indexes) const override;
83 : Qt::DropActions supportedDragActions() const override;
84 :
85 : private:
86 : ThreadNode *nodeFromIndex(const QModelIndex &index) const;
87 : QModelIndex indexFromNode(ThreadNode *node, int column = 0) const;
88 : int findRootIndex(ThreadNode *node) const;
89 : int findChildIndex(ThreadNode *node) const;
90 : void buildUidIndex();
91 :
92 : QList<MailHeader> m_headers; // Owned: flat list of all headers
93 : std::vector<std::unique_ptr<ThreadNode>> m_roots; // Owned: root-level thread nodes
94 : QHash<MailKey, ThreadNode *> m_uidIndex; // T-514: (folderId,UID) → node lookup
95 :
96 : // T-232: Suggestion cache ((folderId,UID) → {text, confidence})
97 : struct SuggestionEntry { QString text; double confidence; };
98 : QHash<MailKey, SuggestionEntry> m_suggestionCache;
99 : };
|