feat: email grouping by date + stability fixes
- EmailTreeModel: hierarchical model for grouped email view (QTreeView) - DateGroupProxyModel: proxy model for date-based grouping logic - MailListView: migrated from QTableView to QTreeView with grouping support - ReaderView: subject frame with shadow, avatar moved to header, body inside header - MainWindow: frameless with rounded corners, 1px border, edge resize, no status bar - Stability fixes for grouping mode switch: * Proper tree cleanup (no double-delete of root) * Bounds checking on all array accesses * Null pointer checks in index/parent/data methods * Date validity checks before grouping * Index validation before accessing m_emails
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QModelIndex>
|
||||
#include <QVariant>
|
||||
#include <QVector>
|
||||
#include <QDateTime>
|
||||
#include <QDate>
|
||||
#include "core/mailitem.h"
|
||||
|
||||
class EmailTreeModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Columns {
|
||||
ColSubject = 0,
|
||||
ColSender = 1,
|
||||
ColDate = 2,
|
||||
ColCount = 3
|
||||
};
|
||||
|
||||
enum Roles {
|
||||
MailIdRole = Qt::UserRole + 1,
|
||||
IsGroupRole = Qt::UserRole + 2,
|
||||
GroupNameRole = Qt::UserRole + 3,
|
||||
GroupIndexRole = Qt::UserRole + 4,
|
||||
MailIndexRole = Qt::UserRole + 5
|
||||
};
|
||||
|
||||
explicit EmailTreeModel(QObject *parent = nullptr);
|
||||
~EmailTreeModel() override;
|
||||
|
||||
// Basic model interface
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||
QModelIndex parent(const QModelIndex &child) const override;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
|
||||
// Email data management
|
||||
void setEmails(const QVector<MailItem> &emails);
|
||||
void clear();
|
||||
|
||||
// Grouping
|
||||
enum GroupMode {
|
||||
NoGrouping = 0,
|
||||
GroupByDate = 1
|
||||
};
|
||||
void setGroupMode(GroupMode mode);
|
||||
GroupMode groupMode() const { return m_groupMode; }
|
||||
|
||||
private:
|
||||
struct TreeItem {
|
||||
enum Type { Group, Mail } type;
|
||||
QString groupName; // for Group 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;
|
||||
|
||||
TreeItem(Type t, TreeItem* p = nullptr) : type(t), parent(p) {}
|
||||
~TreeItem() { qDeleteAll(children); }
|
||||
};
|
||||
|
||||
GroupMode m_groupMode = NoGrouping;
|
||||
QVector<MailItem> m_emails;
|
||||
TreeItem* m_rootItem = nullptr;
|
||||
|
||||
void setupModelData();
|
||||
void buildGroups();
|
||||
QString groupNameForDate(const QDateTime &date) const;
|
||||
int groupIndexForDate(const QDateTime &date) const;
|
||||
void deleteTree(TreeItem* item);
|
||||
};
|
||||
Reference in New Issue
Block a user