data/MailSort.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include "Models.h" | ||
| 4 | #include <QByteArray> | ||
| 5 | #include <QString> | ||
| 6 | #include <QVariant> | ||
| 7 | |||
| 8 | // F100-66: the order of a folder's mail list, flat and threaded. The cache | ||
| 9 | // page queries, the in-memory list window (streamed inserts) and the thread | ||
| 10 | // index derive their order from the same keys, so paging continues exactly | ||
| 11 | // where the loaded rows end. | ||
| 12 | // | ||
| 13 | // Canonical order of a column = its key descending, then UID descending | ||
| 14 | // (Date: date descending with undated mail last, as before). An ascending | ||
| 15 | // sort is the exact reverse of that order. Text keys compare as UTF-8 bytes | ||
| 16 | // (SQLite's BINARY collation), so C++ and SQL agree row by row. | ||
| 17 | struct MailSortOrder { | ||
| 18 | enum class Column { Date, Sender, Recipient, Subject, Size, Star }; | ||
| 19 | Column column = Column::Date; | ||
| 20 | bool ascending = false; | ||
| 21 | |||
| 22 |
4/4✓ Branch 2 → 3 taken 3492 times.
✓ Branch 2 → 5 taken 5 times.
✓ Branch 3 → 4 taken 3490 times.
✓ Branch 3 → 5 taken 2 times.
|
3497 | bool isDefault() const { return column == Column::Date && !ascending; } |
| 23 | 1674 | bool operator==(const MailSortOrder &other) const { | |
| 24 |
4/4✓ Branch 2 → 3 taken 1656 times.
✓ Branch 2 → 5 taken 18 times.
✓ Branch 3 → 4 taken 1640 times.
✓ Branch 3 → 5 taken 16 times.
|
1674 | return column == other.column && ascending == other.ascending; |
| 25 | } | ||
| 26 | 42 | bool operator!=(const MailSortOrder &other) const { return !(*this == other); } | |
| 27 | |||
| 28 | // List column ids ("date", "from", "to", "subject", "size", "star"); | ||
| 29 | // false for ids that cannot be sorted ("status", "suggestion", unknown). | ||
| 30 | static bool columnFromId(const QString &id, Column *column); | ||
| 31 | static QString idOf(Column column); | ||
| 32 | // The direction a first click on a title chooses: newest, largest and | ||
| 33 | // starred first; text from A to Z. | ||
| 34 | static bool defaultAscending(Column column); | ||
| 35 | // Persisted form "<id>:<asc|desc>"; anything unknown reads as the default. | ||
| 36 | QString toString() const; | ||
| 37 | static MailSortOrder fromString(const QString &text); | ||
| 38 | }; | ||
| 39 | |||
| 40 | namespace MailSort { | ||
| 41 | |||
| 42 | // Folded key of a person field ("Name <a@b>", or several of them): the | ||
| 43 | // first display name, else the first address; accents, case and leading | ||
| 44 | // punctuation do not count. | ||
| 45 | QString personKey(const QString &addresses); | ||
| 46 | // Folded key of a subject without reply/forward prefixes ("Re:", "Fwd:", | ||
| 47 | // "AW:", "WG:", …). | ||
| 48 | QString subjectKey(const QString &subject); | ||
| 49 | |||
| 50 | // The column's key of one header, exactly as the SQL expression computes | ||
| 51 | // it: QString for text columns (compared as UTF-8 bytes), qint64 otherwise. | ||
| 52 | // Unused for Date. | ||
| 53 | QVariant key(const MailHeader &header, MailSortOrder::Column column); | ||
| 54 | |||
| 55 | // True when `left` is listed before `right` in `order` (the comparator of | ||
| 56 | // the in-memory window; mirrors the SQL ORDER BY). | ||
| 57 | bool listedBefore(const MailHeader &left, const MailHeader &right, const MailSortOrder &order); | ||
| 58 | |||
| 59 | // The order of a thread list: Date, Sender and Subject as given (threads | ||
| 60 | // by their newest mail, or by their first mail's sender/subject); any other | ||
| 61 | // column falls back to the default (newest first). | ||
| 62 | MailSortOrder threadOrder(const MailSortOrder &order); | ||
| 63 | |||
| 64 | // SQL expression of the column's key over a `headers` row alias (empty | ||
| 65 | // alias = unqualified columns). Unused for Date. MailSortSql registers the | ||
| 66 | // SQL functions on every cache connection: mailjd_sort_key(kind, text) (kind 1 = | ||
| 67 | // personKey, 2 = subjectKey) and mailjd_desc_key(text) (descendingKey). | ||
| 68 | QString sqlKey(MailSortOrder::Column column, const QString &alias = {}); | ||
| 69 | |||
| 70 | // Byte string whose memcmp order is the reverse of `utf8`'s (for texts | ||
| 71 | // without NUL bytes): every byte complemented, then 0xFF appended. | ||
| 72 | QByteArray descendingKey(const QByteArray &utf8); | ||
| 73 | |||
| 74 | } // namespace MailSort | ||
| 75 |