presentation/FolderIconCatalog.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include "data/Models.h" | ||
| 4 | #include <QAbstractListModel> | ||
| 5 | #include <QLoggingCategory> | ||
| 6 | #include <QHash> | ||
| 7 | #include <QList> | ||
| 8 | #include <QString> | ||
| 9 | |||
| 10 | // Folder appearance and properties logging (catalog load, saves, purges). | ||
| 11 | Q_DECLARE_LOGGING_CATEGORY(lcFolderIcons) | ||
| 12 | |||
| 13 | // Material Design Icons name -> code point table (resources/mdi-codemap.csv) | ||
| 14 | // plus the folder default-icon rules of the former Widgets folder tree. | ||
| 15 | // Custom folder icons are stored and synchronized by MDI name | ||
| 16 | // (QSettings folder/icon/<path>); QML renders the code point with the | ||
| 17 | // shared MDI font (Runtime.mdi). | ||
| 18 | class FolderIconCatalog final { | ||
| 19 | public: | ||
| 20 | struct Entry { | ||
| 21 | QString name; | ||
| 22 | int codePoint = 0; | ||
| 23 | }; | ||
| 24 | // Reads the CSV once; false (and an empty catalog) when it is missing. | ||
| 25 | bool load(const QString &csvPath = QStringLiteral(":/mdi-codemap.csv")); | ||
| 26 | 3149 | bool loaded() const { return !m_entries.isEmpty(); } | |
| 27 | 3034 | const QList<Entry> &entries() const { return m_entries; } | |
| 28 | 4 | bool contains(const QString &name) const { return m_codePoints.contains(name); } | |
| 29 | // 0 for an unknown name. | ||
| 30 | 6302 | int codePoint(const QString &name) const { return m_codePoints.value(name, 0); } | |
| 31 | // Special-use flags first (INBOX, \Sent, \Drafts, \Trash, \Archive, | ||
| 32 | // \Junk), then leaf-name heuristics, then "folder-outline". | ||
| 33 | static QString defaultIconName(const FolderInfo &folder); | ||
| 34 | |||
| 35 | private: | ||
| 36 | QList<Entry> m_entries; | ||
| 37 | QHash<QString, int> m_codePoints; | ||
| 38 | }; | ||
| 39 | |||
| 40 | // Filterable icon list for the folder properties picker. The filter is a | ||
| 41 | // case-insensitive substring match on the icon name. | ||
| 42 | class FolderIconListModel final : public QAbstractListModel { | ||
| 43 | Q_OBJECT | ||
| 44 | Q_PROPERTY(QString filter READ filter WRITE setFilter NOTIFY filterChanged) | ||
| 45 | public: | ||
| 46 | enum Role { NameRole = Qt::UserRole + 1, GlyphRole }; | ||
| 47 | explicit FolderIconListModel(const FolderIconCatalog *catalog, QObject *parent = nullptr); | ||
| 48 | int rowCount(const QModelIndex &parent = {}) const override; | ||
| 49 | QVariant data(const QModelIndex &index, int role) const override; | ||
| 50 | QHash<int, QByteArray> roleNames() const override; | ||
| 51 | ✗ | QString filter() const { return m_filter; } | |
| 52 | void setFilter(const QString &filter); | ||
| 53 | // Row of `name` under the current filter, -1 when hidden or unknown. | ||
| 54 | Q_INVOKABLE int rowOf(const QString &name) const; | ||
| 55 | signals: | ||
| 56 | void filterChanged(); | ||
| 57 | |||
| 58 | private: | ||
| 59 | void rebuild(); | ||
| 60 | const FolderIconCatalog *m_catalog; | ||
| 61 | QString m_filter; | ||
| 62 | QList<int> m_rows; // indexes into m_catalog->entries() | ||
| 63 | }; | ||
| 64 |