MailJD nbsp;·nbsp; Test Dashboard nbsp;·nbsp; Coverage
LCOV - code coverage report
Current view: top level - ui - MailListModel.h (source / functions) Coverage Total Hit
Test: MailJD Coverage (Unit + E2E) Lines: 100.0 % 2 2
Test Date: 2026-07-27 17:53:44 Functions: 100.0 % 2 2
Legend: Lines:     hit not hit

            Line data    Source code
       1              : #pragma once
       2              : 
       3              : #include <QAbstractTableModel>
       4              : #include <QHash>
       5              : #include <QList>
       6              : #include <QMimeData>
       7              : #include <QPair>
       8              : 
       9              : #include "data/Models.h"
      10              : 
      11              : // MailListModel displays mail headers in a table format (Star, Subject, From,
      12              : // Date, Size). Designed for use with QSortFilterProxyModel for sorting. Unread
      13              : // (unseen) mails are rendered in bold (FontRole). Star column shows ⭐ for
      14              : // flagged mails.
      15              : class MailListModel : public QAbstractTableModel {
      16         5558 :   Q_OBJECT
      17              : 
      18              : public:
      19              :   // T-514: Composite identity key (folderId, uid) — UIDs are only unique per folder
      20              :   using MailKey = QPair<qint64, qint64>;
      21              :   // Column order: Star/status column first (narrow icon), then attachment
      22              :   // indicator, then content.
      23              :   enum Column { Star = 0, Attachment, Subject, Suggestion, From, Date, Size, ColumnCount };
      24              : 
      25              :   // Custom roles for filtering/sorting beyond Qt::UserRole
      26              :   enum Role {
      27              :     SortRole = Qt::UserRole,       // Raw values for proper sorting
      28              :     FlagsRole = Qt::UserRole + 1,  // quint32 flags bitmask
      29              :     HasAttachmentsRole = Qt::UserRole + 2, // bool: has attachments
      30              :     LabelsRole = Qt::UserRole + 3, // QStringList: IMAP keywords/labels
      31              :     // T-79.E5/M16: search-mode folder badge (display-only, per folderId)
      32              :     FolderBadgeRole = Qt::UserRole + 4,
      33              :     SuggestionConfRole = Qt::UserRole + 10, // double: suggestion confidence
      34              :   };
      35              : 
      36              :   explicit MailListModel(QObject *parent = nullptr);
      37              : 
      38              :   // QAbstractTableModel interface
      39              :   int rowCount(const QModelIndex &parent = {}) const override;
      40              :   int columnCount(const QModelIndex &parent = {}) const override;
      41              :   QVariant data(const QModelIndex &index,
      42              :                 int role = Qt::DisplayRole) const override;
      43              :   QVariant headerData(int section, Qt::Orientation orientation,
      44              :                       int role = Qt::DisplayRole) const override;
      45              : 
      46              :   // Sprint 76 (T-76.B3): re-emit header data so translated column headers
      47              :   // (Subject/From/Date/Size/Has attachment) refresh on a live language switch.
      48              :   void retranslateUi();
      49              : 
      50              :   // T-102: Drag & Drop support
      51              :   Qt::ItemFlags flags(const QModelIndex &index) const override;
      52              :   QStringList mimeTypes() const override;
      53              :   QMimeData *mimeData(const QModelIndexList &indexes) const override;
      54              :   Qt::DropActions supportedDragActions() const override;
      55              : 
      56              :   // --- Data management ---
      57              : 
      58              :   // Replace all headers (initial load from cache).
      59              :   void setHeaders(const QList<MailHeader> &headers);
      60              : 
      61              :   // Append new headers (incremental sync from IMAP).
      62              :   void appendHeaders(const QList<MailHeader> &headers);
      63              : 
      64              :   // Clear all data.
      65              :   void clear();
      66              : 
      67              :   // Update flags for a specific UID. Emits dataChanged for the row.
      68              :   // T-514: folderId required for composite key lookup.
      69              :   void updateFlags(qint64 uid, quint32 newFlags, qint64 folderId);
      70              : 
      71              :   // T-71: Update attachment status for a row (called after storeAttachments).
      72              :   void setHasAttachments(qint64 uid, qint64 folderId, bool has);
      73              : 
      74              :   // Remove a mail by UID. Uses beginRemoveRows/endRemoveRows.
      75              :   // T-514: folderId required for composite key lookup.
      76              :   void removeByUid(qint64 uid, qint64 folderId);
      77              : 
      78              :   // T-525/Cx8: Batch remove — single rebuild instead of O(N²)
      79              :   // T-514: folderId required (all UIDs must be from the same folder).
      80              :   void removeByUids(const QList<qint64> &uids, qint64 folderId);
      81              : 
      82              :   // Get the header at a given row. Returns nullptr if out of range.
      83              :   const MailHeader *headerAt(int row) const;
      84              :   MailHeader *mutableHeaderAt(int row);
      85              : 
      86              :   // Get the UID at a given row. Returns -1 if out of range.
      87              :   qint64 uidAt(int row) const;
      88              : 
      89              :   // Find the row index for a given UID. Returns -1 if not found.
      90              :   // T-514: folderId required for composite key lookup.
      91              :   int rowForUid(qint64 uid, qint64 folderId) const;
      92              : 
      93              :   // Count of unseen (unread) mails in the current model.
      94              :   int unreadCount() const;
      95              : 
      96              :   // T-099: Access the full header list for thread model population.
      97           24 :   const QList<MailHeader> &allHeaders() const { return m_headers; }
      98              : 
      99              :   // T-232: Set/clear folder suggestion for a specific UID.
     100              :   // T-514: folderId required for composite key lookup.
     101              :   void setSuggestion(qint64 uid, qint64 folderId, const QString &text, double confidence);
     102              :   void clearSuggestions();
     103              : 
     104              :   // T-79.E5/M16: search-mode folder badges. Register before populating the
     105              :   // model with search results; clear when leaving search mode.
     106              :   void setFolderBadge(qint64 folderId, const QString &folderName);
     107              :   void clearFolderBadges();
     108              : 
     109              : public:
     110              :   // 67.B4: humanized date for the Date column (shared with
     111              :   // MailThreadModel). Today "14:32" · yesterday "Yesterday" · this week
     112              :   // "Mon" · this year "12. May" · older "12.05.2024".
     113              :   static QString formatDate(const QDateTime &dt);
     114              : 
     115              : private:
     116              : 
     117              :   // Format size for display: "1.2 KB", "3.4 MB"
     118              :   static QString formatSize(qint64 bytes);
     119              : 
     120              :   // T-115: Rebuild the UID→row index from m_headers.
     121              :   void rebuildUidIndex();
     122              : 
     123              :   QList<MailHeader> m_headers;
     124              : 
     125              :   // T-514: O(1) (folderId,UID)→row lookup index.
     126              :   // Maintained in sync with m_headers by all mutating methods.
     127              :   QHash<MailKey, int> m_uidIndex;
     128              : 
     129              :   // T-116: Cached unread (unseen) count — avoids O(n) scan on each query.
     130              :   // Maintained by all mutating methods (setHeaders, appendHeaders,
     131              :   // updateFlags, removeByUid, clear).
     132              :   int m_unreadCount = 0;
     133              : 
     134              :   // T-232: Suggestion cache — (folderId,UID) → display text + confidence
     135              :   struct SuggestionData {
     136              :     QString text;       // e.g. "→ Projekte 96%"
     137              :     double confidence;  // for color coding
     138              :   };
     139              :   QHash<MailKey, SuggestionData> m_suggestionCache;
     140              : 
     141              :   // T-79.E5/M16: search-mode folder badges (folderId → display name).
     142              :   // Painted as a "[folder] " prefix in the Subject column; the underlying
     143              :   // MailHeader::subject stays clean so replies/forwards never carry it.
     144              :   QHash<qint64, QString> m_folderBadges;
     145              : };
        

Generated by: LCOV version 2.0-1