feat: EmailTreeModel grouping modes + MailListView integration
- EmailTreeModel: 4 grouping modes * NoGrouping - flat list * GroupByDate - chronological groups (Hoy, Ayer, Esta semana...) * GroupByThread - conversations with expandable threads (ThreadId from References/In-Reply-To/Message-ID) * GroupBySender - groups by sender email/name - EmailTreeModel thread support: * ThreadItem type with expand/collapse * ThreadId extraction via ThreadUtils (References > In-Reply-To > Message-ID) * Double-click thread node toggles expansion * Threads sorted by newest email first, emails within thread oldest first - EmailTreeModel sender grouping: * Groups by sender name/email * Senders sorted by newest email first * Emails within group newest first - MailListView: Added 'Agrupar por remitente' to group-by combo - MailListView: Double-click thread node toggles expansion (not open mail) - ThreadUtils: parseReferencesHeader, extractThreadId, generateThreadId
This commit is contained in:
@@ -25,7 +25,10 @@ public:
|
||||
IsGroupRole = Qt::UserRole + 2,
|
||||
GroupNameRole = Qt::UserRole + 3,
|
||||
GroupIndexRole = Qt::UserRole + 4,
|
||||
MailIndexRole = Qt::UserRole + 5
|
||||
MailIndexRole = Qt::UserRole + 5,
|
||||
IsThreadRole = Qt::UserRole + 6,
|
||||
ThreadIdRole = Qt::UserRole + 7,
|
||||
IsThreadExpandedRole = Qt::UserRole + 8
|
||||
};
|
||||
|
||||
explicit EmailTreeModel(QObject *parent = nullptr);
|
||||
@@ -47,20 +50,28 @@ public:
|
||||
// Grouping
|
||||
enum GroupMode {
|
||||
NoGrouping = 0,
|
||||
GroupByDate = 1
|
||||
GroupByDate = 1,
|
||||
GroupByThread = 2,
|
||||
GroupBySender = 3
|
||||
};
|
||||
void setGroupMode(GroupMode mode);
|
||||
GroupMode groupMode() const { return m_groupMode; }
|
||||
|
||||
// Thread expansion
|
||||
void setThreadExpanded(const QString& threadId, bool expanded);
|
||||
bool isThreadExpanded(const QString& threadId) const;
|
||||
|
||||
private:
|
||||
struct TreeItem {
|
||||
enum Type { Group, Mail } type;
|
||||
enum Type { Group, Mail, Thread } type;
|
||||
QString groupName; // for Group type
|
||||
QString threadId; // for Thread type
|
||||
int groupIndex = -1; // for Group type
|
||||
int mailIndex = -1; // for Mail type (index in m_emails)
|
||||
QVector<TreeItem*> children;
|
||||
TreeItem* parent = nullptr;
|
||||
int row = -1;
|
||||
bool expanded = true; // for Thread type
|
||||
|
||||
TreeItem(Type t, TreeItem* p = nullptr) : type(t), parent(p) {}
|
||||
~TreeItem() { qDeleteAll(children); }
|
||||
@@ -69,10 +80,15 @@ private:
|
||||
GroupMode m_groupMode = NoGrouping;
|
||||
QVector<MailItem> m_emails;
|
||||
TreeItem* m_rootItem = nullptr;
|
||||
QSet<QString> m_expandedThreads;
|
||||
|
||||
void setupModelData();
|
||||
void buildGroups();
|
||||
void buildThreads();
|
||||
void buildSenderGroups();
|
||||
QString groupNameForDate(const QDateTime &date) const;
|
||||
int groupIndexForDate(const QDateTime &date) const;
|
||||
void deleteTree(TreeItem* item);
|
||||
void buildThreadTree();
|
||||
QString extractThreadId(const MailItem& mail) const;
|
||||
};
|
||||
Reference in New Issue
Block a user