data/TemplateStore.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <QJsonObject> | ||
| 4 | #include <QList> | ||
| 5 | #include <QString> | ||
| 6 | #include <optional> | ||
| 7 | |||
| 8 | // Sprint 108 S108.9.5 (D-27): message templates — a named subject and text | ||
| 9 | // the user saves from a message and inserts into another (`template <name>`, | ||
| 10 | // Ctrl+Shift+T, the composer's ⋯ menu). A template keeps the text it was | ||
| 11 | // saved with: formatted templates carry the HTML body fragment written by | ||
| 12 | // MailHtmlWriter plus the plain version, plain ones only the text. Neither | ||
| 13 | // the signature nor the quote of a reply is part of a template. | ||
| 14 | // | ||
| 15 | // Stored in <profile>/templates.json (owner-only, atomic, bounded). Names | ||
| 16 | // are unique without regard to case: saving under an existing name replaces | ||
| 17 | // that template. | ||
| 18 | struct MailTemplate { | ||
| 19 | QString id; | ||
| 20 | QString name; | ||
| 21 | QString subject; | ||
| 22 | QString html; // "" = plain template | ||
| 23 | QString text; | ||
| 24 | }; | ||
| 25 | |||
| 26 | class TemplateStore { | ||
| 27 | public: | ||
| 28 | static constexpr qint64 MaxFileBytes = 8 * 1024 * 1024; | ||
| 29 | static constexpr int MaxTemplates = 100; | ||
| 30 | static constexpr qint64 MaxTemplateBytes = 512 * 1024; | ||
| 31 | static constexpr int MaxNameChars = 120; | ||
| 32 | |||
| 33 | 1603 | explicit TemplateStore(QString path = {}) : m_path(std::move(path)) {} | |
| 34 | static QString pathFor(const QString &profileDirectory); | ||
| 35 | |||
| 36 | // Reads the file (missing file = no templates). A malformed or oversized | ||
| 37 | // file is refused as a whole and reported through `error`. | ||
| 38 | bool load(QString *error = nullptr); | ||
| 39 | bool save(QString *error = nullptr) const; | ||
| 40 | |||
| 41 | // Sorted by name (case-insensitive). | ||
| 42 | 45 | const QList<MailTemplate> &templates() const { return m_templates; } | |
| 43 | std::optional<MailTemplate> find(const QString &id) const; | ||
| 44 | std::optional<MailTemplate> findByName(const QString &name) const; | ||
| 45 | // Inserts, or replaces the template with the same id or name. Refuses an | ||
| 46 | // empty or multi-line name, an oversized body and the 101st template; | ||
| 47 | // the reason goes to `error` ("name", "size", "count"). | ||
| 48 | std::optional<MailTemplate> upsert(MailTemplate value, QString *error = nullptr); | ||
| 49 | bool rename(const QString &id, const QString &name, QString *error = nullptr); | ||
| 50 | bool remove(const QString &id); | ||
| 51 | |||
| 52 | static QJsonObject toJson(const MailTemplate &value); | ||
| 53 | static std::optional<MailTemplate> fromJson(const QJsonObject &object); | ||
| 54 | |||
| 55 | private: | ||
| 56 | void sort(); | ||
| 57 | static bool validName(const QString &name); | ||
| 58 | |||
| 59 | QString m_path; | ||
| 60 | QList<MailTemplate> m_templates; | ||
| 61 | }; | ||
| 62 |