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
@@ -38,10 +38,17 @@ template <> constexpr inline auto EmailListModel::qt_create_metaobjectdata<qt_me
{
namespace QMC = QtMocConstants;
QtMocHelpers::StringRefStorage qt_stringData {
"EmailListModel"
"EmailListModel",
"totalCountChanged",
"",
"count"
};
QtMocHelpers::UintData qt_methods {
// Signal 'totalCountChanged'
QtMocHelpers::SignalData<void(int)>(1, 2, QMC::AccessPublic, QMetaType::Void, {{
{ QMetaType::Int, 3 },
}}),
};
QtMocHelpers::UintData qt_properties {
};
@@ -51,7 +58,7 @@ template <> constexpr inline auto EmailListModel::qt_create_metaobjectdata<qt_me
qt_methods, qt_properties, qt_enums);
}
Q_CONSTINIT const QMetaObject EmailListModel::staticMetaObject = { {
QMetaObject::SuperData::link<QAbstractTableModel::staticMetaObject>(),
QMetaObject::SuperData::link<QAbstractListModel::staticMetaObject>(),
qt_staticMetaObjectStaticContent<qt_meta_tag_ZN14EmailListModelE_t>.stringdata,
qt_staticMetaObjectStaticContent<qt_meta_tag_ZN14EmailListModelE_t>.data,
qt_static_metacall,
@@ -63,10 +70,16 @@ Q_CONSTINIT const QMetaObject EmailListModel::staticMetaObject = { {
void EmailListModel::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
auto *_t = static_cast<EmailListModel *>(_o);
(void)_t;
(void)_c;
(void)_id;
(void)_a;
if (_c == QMetaObject::InvokeMetaMethod) {
switch (_id) {
case 0: _t->totalCountChanged((*reinterpret_cast<std::add_pointer_t<int>>(_a[1]))); break;
default: ;
}
}
if (_c == QMetaObject::IndexOfMethod) {
if (QtMocHelpers::indexOfMethod<void (EmailListModel::*)(int )>(_a, &EmailListModel::totalCountChanged, 0))
return;
}
}
const QMetaObject *EmailListModel::metaObject() const
@@ -79,12 +92,30 @@ void *EmailListModel::qt_metacast(const char *_clname)
if (!_clname) return nullptr;
if (!strcmp(_clname, qt_staticMetaObjectStaticContent<qt_meta_tag_ZN14EmailListModelE_t>.strings))
return static_cast<void*>(this);
return QAbstractTableModel::qt_metacast(_clname);
return QAbstractListModel::qt_metacast(_clname);
}
int EmailListModel::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QAbstractTableModel::qt_metacall(_c, _id, _a);
_id = QAbstractListModel::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
if (_id < 1)
qt_static_metacall(this, _c, _id, _a);
_id -= 1;
}
if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
if (_id < 1)
*reinterpret_cast<QMetaType *>(_a[0]) = QMetaType();
_id -= 1;
}
return _id;
}
// SIGNAL 0
void EmailListModel::totalCountChanged(int _t1)
{
QMetaObject::activate<void>(this, &staticMetaObject, 0, nullptr, _t1);
}
QT_WARNING_POP