feat: Pagination/virtualization (fetchMore) for EmailListModel

- EmailListModel: QAbstractListModel with canFetchMore/fetchMore
  * Batch loading (default 50 emails per fetch)
  * Total count query for scrollbar
  * TotalCountChanged signal
  * Paginated DB queries: findAllPaginated, findByFolderIdPaginated
  * Count queries: countAll, countByFolderId

- MailItemDao: new paginated methods
  * findAllPaginated(offset, limit, filters...)
  * findByFolderIdPaginated(folderId, offset, limit, filters...)
  * countAll(filters...), countByFolderId(folderId, filters...)

- MailListView: scroll-triggered fetchMore
  * Connects verticalScrollBar valueChanged on both TreeView and ListView
  * Triggers fetchMore at 90% scroll threshold
  * onRowsInserted updates EmailTreeModel when new emails arrive
  * Works in both normal (tree) and compact (list) views
This commit is contained in:
2026-08-25 22:20:06 +02:00
parent 6e6fdf9c21
commit 68d237c873
77 changed files with 16718 additions and 18159 deletions
+20 -12
View File
@@ -6,7 +6,7 @@
#include <QByteArray>
#include "../db/dao/mailitemdao.h"
class EmailListModel : public QAbstractTableModel
class EmailListModel : public QAbstractListModel
{
Q_OBJECT
public:
@@ -25,22 +25,19 @@ public:
FileIdRole,
SizeRole,
MessageIdRole,
SenderInitialRole // computed from sender
};
// Column indices (match role order for simplicity)
enum Columns {
ColSubject = 0,
ColSender = 1,
ColDate = 2,
ColCount = 3 // number of visible columns
SenderInitialRole, // computed from sender
ThreadIdRole,
InReplyToRole,
ReferencesRole,
IsPinnedRole
};
// QAbstractListModel interface
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;
QHash<int, QByteArray> roleNames() const override;
bool canFetchMore(const QModelIndex &parent) const override;
void fetchMore(const QModelIndex &parent) override;
// Set the folderId to filter emails; -1 means all folders
void setFolderId(int folderId);
@@ -52,10 +49,18 @@ public:
void setShowUnreadOnly(bool show);
void setShowFlaggedOnly(bool show);
void setShowHasAttachments(bool show);
// Set batch size for pagination
void setBatchSize(int size) { m_batchSize = size; }
// Get all emails currently in the model (after filtering)
const QVector<MailItem>& emails() const { return m_emails; }
// Total count of emails matching filters (including unloaded)
int totalCount() const { return m_totalCount; }
signals:
void totalCountChanged(int count);
private:
QVector<MailItem> m_emails;
int m_folderId{-1}; // -1 means all folders
@@ -63,5 +68,8 @@ private:
bool m_unreadOnly{false};
bool m_flaggedOnly{false};
bool m_hasAttachments{false};
int m_batchSize{50}; // emails per fetch
int m_loadedCount{0}; // how many emails currently loaded
int m_totalCount{0}; // total matching emails in DB
};
#endif // EMAILLISTMODEL_H