File indexing completed on 2025-01-26 05:08:09
0001 #pragma once 0002 0003 /* 0004 * SPDX-FileCopyrightText: 2003-2007 Craig Drummond <craig@kde.org> 0005 * SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "Family.h" 0009 #include "FcQuery.h" 0010 #include "File.h" 0011 #include "FontFilter.h" 0012 #include "FontInst.h" 0013 #include "JobRunner.h" 0014 #include "Misc.h" 0015 #include "Style.h" 0016 #include <KFileItem> 0017 #include <KIO/Job> 0018 #include <QAbstractItemModel> 0019 #include <QHash> 0020 #include <QList> 0021 #include <QModelIndex> 0022 #include <QSet> 0023 #include <QSortFilterProxyModel> 0024 #include <QTreeView> 0025 #include <QUrl> 0026 #include <QVariant> 0027 0028 class QMenu; 0029 class QMimeData; 0030 class QTimer; 0031 0032 #define KFI_FONT_DRAG_MIME "kfontinst/fontlist" 0033 0034 namespace KFI 0035 { 0036 class CFontItem; 0037 class CFontItem; 0038 class CFamilyItem; 0039 class CGroupListItem; 0040 class Style; 0041 0042 enum EColumns { 0043 COL_FONT, 0044 COL_STATUS, 0045 0046 NUM_COLS, 0047 }; 0048 0049 typedef QList<CFamilyItem *> CFamilyItemCont; 0050 typedef QList<CFontItem *> CFontItemCont; 0051 typedef QHash<QString, CFamilyItem *> CFamilyItemHash; 0052 0053 class CFontList : public QAbstractItemModel 0054 { 0055 Q_OBJECT 0056 0057 private: 0058 enum EMsgType { 0059 MSG_ADD, 0060 MSG_DEL, 0061 0062 NUM_MSGS_TYPES, 0063 }; 0064 0065 public: 0066 static const QStringList fontMimeTypes; 0067 0068 public: 0069 static QStringList compact(const QStringList &fonts); 0070 0071 CFontList(QWidget *parent = nullptr); 0072 ~CFontList() override; 0073 0074 QVariant data(const QModelIndex &index, int role) const override; 0075 Qt::ItemFlags flags(const QModelIndex &index) const override; 0076 Qt::DropActions supportedDropActions() const override; 0077 QMimeData *mimeData(const QModelIndexList &indexes) const override; 0078 QStringList mimeTypes() const override; 0079 QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; 0080 QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; 0081 QModelIndex parent(const QModelIndex &index) const override; 0082 int rowCount(const QModelIndex &parent = QModelIndex()) const override; 0083 int columnCount(const QModelIndex &parent = QModelIndex()) const override; 0084 int row(const CFamilyItem *fam) const 0085 { 0086 return m_families.indexOf((CFamilyItem *)fam); 0087 } 0088 void forceNewPreviews(); 0089 const CFamilyItemCont &families() const 0090 { 0091 return m_families; 0092 } 0093 QModelIndex createIndex(int row, int column, void *data = nullptr) const 0094 { 0095 return QAbstractItemModel::createIndex(row, column, data); 0096 } 0097 bool hasFamily(const QString &family) 0098 { 0099 return nullptr != findFamily(family); 0100 } 0101 void refresh(bool allowSys, bool allowUser); 0102 bool allowSys() const 0103 { 0104 return m_allowSys; 0105 } 0106 bool allowUser() const 0107 { 0108 return m_allowUser; 0109 } 0110 void getFamilyStats(QSet<QString> &enabled, QSet<QString> &disabled, QSet<QString> &partial); 0111 void getFoundries(QSet<QString> &foundries) const; 0112 QString whatsThis() const; 0113 void setSlowUpdates(bool slow); 0114 bool slowUpdates() const 0115 { 0116 return m_slowUpdates; 0117 } 0118 0119 Q_SIGNALS: 0120 0121 void listingPercent(int p); 0122 0123 public Q_SLOTS: 0124 0125 void unsetSlowUpdates(); 0126 void load(); 0127 0128 private Q_SLOTS: 0129 0130 void dbusServiceOwnerChanged(const QString &name, const QString &from, const QString &to); 0131 void fontList(int pid, const QList<KFI::Families> &families); 0132 void fontsAdded(const KFI::Families &families); 0133 void fontsRemoved(const KFI::Families &families); 0134 0135 private: 0136 void storeSlowedMessage(const Families &families, EMsgType type); 0137 void actionSlowedUpdates(bool sys); 0138 void addFonts(const FamilyCont &families, bool sys); 0139 void removeFonts(const FamilyCont &families, bool sys); 0140 CFamilyItem *findFamily(const QString &familyName); 0141 0142 private: 0143 CFamilyItemCont m_families; 0144 CFamilyItemHash m_familyHash; 0145 bool m_blockSignals, m_allowSys, m_allowUser, m_slowUpdates; 0146 static int theirPreviewSize; 0147 FamilyCont m_slowedMsgs[NUM_MSGS_TYPES][FontInst::FOLDER_COUNT]; 0148 }; 0149 0150 class CFontModelItem 0151 { 0152 public: 0153 CFontModelItem(CFontModelItem *p) 0154 : m_parent(p) 0155 , m_isSystem(false) 0156 { 0157 } 0158 virtual ~CFontModelItem() 0159 { 0160 } 0161 0162 CFontModelItem *parent() const 0163 { 0164 return m_parent; 0165 } 0166 bool isFamily() const 0167 { 0168 return nullptr == m_parent; 0169 } 0170 bool isFont() const 0171 { 0172 return nullptr != m_parent; 0173 } 0174 bool isSystem() const 0175 { 0176 return m_isSystem; 0177 } 0178 void setIsSystem(bool sys) 0179 { 0180 m_isSystem = sys; 0181 } 0182 virtual int rowNumber() const = 0; 0183 0184 protected: 0185 CFontModelItem *m_parent; 0186 bool m_isSystem; 0187 }; 0188 0189 class CFamilyItem : public CFontModelItem 0190 { 0191 public: 0192 enum EStatus { 0193 ENABLED, 0194 PARTIAL, 0195 DISABLED, 0196 }; 0197 0198 CFamilyItem(CFontList &p, const Family &f, bool sys); 0199 ~CFamilyItem() override; 0200 0201 bool operator==(const CFamilyItem &other) const 0202 { 0203 return m_name == other.m_name; 0204 } 0205 0206 bool addFonts(const StyleCont &styles, bool sys); 0207 const QString &name() const 0208 { 0209 return m_name; 0210 } 0211 const CFontItemCont &fonts() const 0212 { 0213 return m_fonts; 0214 } 0215 void addFont(CFontItem *font, bool update = true); 0216 void removeFont(CFontItem *font, bool update); 0217 void refresh(); 0218 bool updateStatus(); 0219 bool updateRegularFont(CFontItem *font); 0220 CFontItem *findFont(quint32 style, bool sys); 0221 int rowNumber() const override 0222 { 0223 return m_parent.row(this); 0224 } 0225 int row(const CFontItem *font) const 0226 { 0227 return m_fonts.indexOf((CFontItem *)font); 0228 } 0229 EStatus status() const 0230 { 0231 return m_status; 0232 } 0233 EStatus realStatus() const 0234 { 0235 return m_realStatus; 0236 } 0237 CFontItem *regularFont() 0238 { 0239 return m_regularFont; 0240 } 0241 int fontCount() const 0242 { 0243 return m_fontCount; 0244 } 0245 void getFoundries(QSet<QString> &foundries) const; 0246 bool slowUpdates() const 0247 { 0248 return m_parent.slowUpdates(); 0249 } 0250 0251 private: 0252 bool usable(const CFontItem *font, bool root); 0253 0254 private: 0255 QString m_name; 0256 CFontItemCont m_fonts; 0257 int m_fontCount; 0258 EStatus m_status, m_realStatus; 0259 CFontItem *m_regularFont; // 'RegularFont' is font nearest to 'Regular' style, and used for previews. 0260 CFontList &m_parent; 0261 }; 0262 0263 class CFontItem : public CFontModelItem 0264 { 0265 public: 0266 CFontItem(CFontModelItem *p, const Style &s, bool sys); 0267 ~CFontItem() override 0268 { 0269 } 0270 0271 void refresh(); 0272 QString name() const 0273 { 0274 return family() + QString::fromLatin1(", ") + m_styleName; 0275 } 0276 bool isEnabled() const 0277 { 0278 return m_enabled; 0279 } 0280 bool isHidden() const 0281 { 0282 return !m_enabled; 0283 } 0284 bool isBitmap() const 0285 { 0286 return !m_style.scalable(); 0287 } 0288 const QString &fileName() const 0289 { 0290 return (*m_style.files().begin()).path(); 0291 } 0292 const QString &style() const 0293 { 0294 return m_styleName; 0295 } 0296 quint32 styleInfo() const 0297 { 0298 return m_style.value(); 0299 } 0300 int index() const 0301 { 0302 return (*m_style.files().begin()).index(); 0303 } 0304 const QString &family() const 0305 { 0306 return (static_cast<CFamilyItem *>(parent()))->name(); 0307 } 0308 int rowNumber() const override 0309 { 0310 return (static_cast<CFamilyItem *>(parent()))->row(this); 0311 } 0312 const FileCont &files() const 0313 { 0314 return m_style.files(); 0315 } 0316 qulonglong writingSystems() const 0317 { 0318 return m_style.writingSystems(); 0319 } 0320 QUrl url() const 0321 { 0322 return CJobRunner::encode(family(), styleInfo(), isSystem()); 0323 } 0324 void removeFile(const File &f) 0325 { 0326 m_style.remove(f); 0327 } 0328 void removeFiles(const FileCont &f) 0329 { 0330 m_style.removeFiles(f); 0331 } 0332 void addFile(const File &f) 0333 { 0334 m_style.add(f); 0335 } 0336 void addFiles(const FileCont &f) 0337 { 0338 m_style.addFiles(f); 0339 } 0340 0341 private: 0342 QString m_styleName; 0343 Style m_style; 0344 bool m_enabled; 0345 }; 0346 0347 class CFontListSortFilterProxy : public QSortFilterProxyModel 0348 { 0349 Q_OBJECT 0350 0351 public: 0352 CFontListSortFilterProxy(QObject *parent, QAbstractItemModel *model); 0353 ~CFontListSortFilterProxy() override 0354 { 0355 } 0356 0357 QVariant data(const QModelIndex &idx, int role) const override; 0358 bool acceptFont(CFontItem *fnt, bool checkFontText) const; 0359 bool acceptFamily(CFamilyItem *fam) const; 0360 bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; 0361 bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; 0362 void setFilterGroup(CGroupListItem *grp); 0363 CGroupListItem *filterGroup() 0364 { 0365 return m_group; 0366 } 0367 0368 void setFilterText(const QString &text); 0369 void setFilterCriteria(CFontFilter::ECriteria crit, qulonglong ws, const QStringList &ft); 0370 0371 private Q_SLOTS: 0372 0373 void timeout(); 0374 void fcResults(); 0375 0376 Q_SIGNALS: 0377 0378 void refresh(); 0379 0380 private: 0381 QString filterText() const 0382 { 0383 return CFontFilter::CRIT_FONTCONFIG == m_filterCriteria ? (m_fcQuery ? m_fcQuery->font() : QString()) : m_filterText; 0384 } 0385 0386 private: 0387 CGroupListItem *m_group; 0388 QString m_filterText; 0389 CFontFilter::ECriteria m_filterCriteria; 0390 qulonglong m_filterWs; 0391 QStringList m_filterTypes; 0392 QTimer *m_timer; 0393 CFcQuery *m_fcQuery; 0394 }; 0395 0396 class CFontListView : public QTreeView 0397 { 0398 Q_OBJECT 0399 0400 public: 0401 CFontListView(QWidget *parent, CFontList *model); 0402 ~CFontListView() override 0403 { 0404 } 0405 0406 void getFonts(CJobRunner::ItemList &urls, QStringList &fontNames, QSet<Misc::TFont> *fonts, bool selected, bool getEnabled = true, bool getDisabled = true); 0407 QSet<QString> getFiles(); 0408 void getPrintableFonts(QSet<Misc::TFont> &items, bool selected); 0409 void setFilterGroup(CGroupListItem *grp); 0410 void stats(int &enabled, int &disabled, int &partial); 0411 void selectedStatus(bool &enabled, bool &disabled); 0412 QModelIndexList allFonts(); 0413 void selectFirstFont(); 0414 QModelIndexList getSelectedItems(); 0415 0416 Q_SIGNALS: 0417 0418 void del(); 0419 void print(); 0420 void enable(); 0421 void disable(); 0422 void fontsDropped(const QSet<QUrl> &); 0423 void itemsSelected(const QModelIndexList &); 0424 void refresh(); 0425 void reload(); 0426 0427 public Q_SLOTS: 0428 0429 void listingPercent(int percent); 0430 void refreshFilter(); 0431 void filterText(const QString &text); 0432 void filterCriteria(int crit, qulonglong ws, const QStringList &ft); 0433 0434 private Q_SLOTS: 0435 0436 void setSortColumn(int col); 0437 void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) override; 0438 void itemCollapsed(const QModelIndex &index); 0439 void view(); 0440 0441 private: 0442 QModelIndexList allIndexes(); 0443 void startDrag(Qt::DropActions supportedActions) override; 0444 void dragEnterEvent(QDragEnterEvent *event) override; 0445 void dropEvent(QDropEvent *event) override; 0446 void contextMenuEvent(QContextMenuEvent *ev) override; 0447 bool viewportEvent(QEvent *event) override; 0448 0449 private: 0450 CFontListSortFilterProxy *m_proxy; 0451 CFontList *m_model; 0452 QMenu *m_menu; 0453 QAction *m_deleteAct, *m_enableAct, *m_disableAct, *m_printAct, *m_viewAct; 0454 bool m_allowDrops; 0455 }; 0456 0457 }