1 #pragma once 2 3 /* 4 * SPDX-FileCopyrightText: 2003-2007 Craig Drummond <craig@kde.org> 5 * SPDX-License-Identifier: GPL-2.0-or-later 6 */ 7 8 #include "Family.h" 9 #include "FcQuery.h" 10 #include "File.h" 11 #include "FontFilter.h" 12 #include "FontInst.h" 13 #include "JobRunner.h" 14 #include "Misc.h" 15 #include "Style.h" 16 #include <KFileItem> 17 #include <KIO/Job> 18 #include <QAbstractItemModel> 19 #include <QHash> 20 #include <QList> 21 #include <QModelIndex> 22 #include <QSet> 23 #include <QSortFilterProxyModel> 24 #include <QTreeView> 25 #include <QUrl> 26 #include <QVariant> 27 28 class KFileItem; 29 class QMenu; 30 class QMimeData; 31 class QTimer; 32 33 #define KFI_FONT_DRAG_MIME "kfontinst/fontlist" 34 35 namespace KFI 36 { 37 class CFontItem; 38 class CFontItem; 39 class CFamilyItem; 40 class CGroupListItem; 41 class Style; 42 43 enum EColumns { 44 COL_FONT, 45 COL_STATUS, 46 47 NUM_COLS, 48 }; 49 50 typedef QList<CFamilyItem *> CFamilyItemCont; 51 typedef QList<CFontItem *> CFontItemCont; 52 typedef QHash<QString, CFamilyItem *> CFamilyItemHash; 53 54 class CFontList : public QAbstractItemModel 55 { 56 Q_OBJECT 57 58 private: 59 enum EMsgType { 60 MSG_ADD, 61 MSG_DEL, 62 63 NUM_MSGS_TYPES, 64 }; 65 66 public: 67 static const QStringList fontMimeTypes; 68 69 public: 70 static QStringList compact(const QStringList &fonts); 71 72 CFontList(QWidget *parent = nullptr); 73 ~CFontList() override; 74 75 QVariant data(const QModelIndex &index, int role) const override; 76 Qt::ItemFlags flags(const QModelIndex &index) const override; 77 Qt::DropActions supportedDropActions() const override; 78 QMimeData *mimeData(const QModelIndexList &indexes) const override; 79 QStringList mimeTypes() const override; 80 QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; 81 QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; 82 QModelIndex parent(const QModelIndex &index) const override; 83 int rowCount(const QModelIndex &parent = QModelIndex()) const override; 84 int columnCount(const QModelIndex &parent = QModelIndex()) const override; row(const CFamilyItem * fam)85 int row(const CFamilyItem *fam) const 86 { 87 return itsFamilies.indexOf((CFamilyItem *)fam); 88 } 89 void forceNewPreviews(); families()90 const CFamilyItemCont &families() const 91 { 92 return itsFamilies; 93 } 94 QModelIndex createIndex(int row, int column, void *data = nullptr) const 95 { 96 return QAbstractItemModel::createIndex(row, column, data); 97 } hasFamily(const QString & family)98 bool hasFamily(const QString &family) 99 { 100 return nullptr != findFamily(family); 101 } 102 void refresh(bool allowSys, bool allowUser); allowSys()103 bool allowSys() const 104 { 105 return itsAllowSys; 106 } allowUser()107 bool allowUser() const 108 { 109 return itsAllowUser; 110 } 111 void getFamilyStats(QSet<QString> &enabled, QSet<QString> &disabled, QSet<QString> &partial); 112 void getFoundries(QSet<QString> &foundries) const; 113 QString whatsThis() const; 114 void setSlowUpdates(bool slow); slowUpdates()115 bool slowUpdates() const 116 { 117 return itsSlowUpdates; 118 } 119 120 Q_SIGNALS: 121 122 void listingPercent(int p); 123 124 public Q_SLOTS: 125 126 void unsetSlowUpdates(); 127 void load(); 128 129 private Q_SLOTS: 130 131 void dbusServiceOwnerChanged(const QString &name, const QString &from, const QString &to); 132 void fontList(int pid, const QList<KFI::Families> &families); 133 void fontsAdded(const KFI::Families &families); 134 void fontsRemoved(const KFI::Families &families); 135 136 private: 137 void storeSlowedMessage(const Families &families, EMsgType type); 138 void actionSlowedUpdates(bool sys); 139 void addFonts(const FamilyCont &families, bool sys); 140 void removeFonts(const FamilyCont &families, bool sys); 141 CFamilyItem *findFamily(const QString &familyName); 142 143 private: 144 CFamilyItemCont itsFamilies; 145 CFamilyItemHash itsFamilyHash; 146 bool itsBlockSignals, itsAllowSys, itsAllowUser, itsSlowUpdates; 147 static int theirPreviewSize; 148 FamilyCont itsSlowedMsgs[NUM_MSGS_TYPES][FontInst::FOLDER_COUNT]; 149 }; 150 151 class CFontModelItem 152 { 153 public: CFontModelItem(CFontModelItem * p)154 CFontModelItem(CFontModelItem *p) 155 : itsParent(p) 156 , itsIsSystem(false) 157 { 158 } ~CFontModelItem()159 virtual ~CFontModelItem() 160 { 161 } 162 parent()163 CFontModelItem *parent() const 164 { 165 return itsParent; 166 } isFamily()167 bool isFamily() const 168 { 169 return nullptr == itsParent; 170 } isFont()171 bool isFont() const 172 { 173 return nullptr != itsParent; 174 } isSystem()175 bool isSystem() const 176 { 177 return itsIsSystem; 178 } setIsSystem(bool sys)179 void setIsSystem(bool sys) 180 { 181 itsIsSystem = sys; 182 } 183 virtual int rowNumber() const = 0; 184 185 protected: 186 CFontModelItem *itsParent; 187 bool itsIsSystem; 188 }; 189 190 class CFamilyItem : public CFontModelItem 191 { 192 public: 193 enum EStatus { 194 ENABLED, 195 PARTIAL, 196 DISABLED, 197 }; 198 199 CFamilyItem(CFontList &p, const Family &f, bool sys); 200 ~CFamilyItem() override; 201 202 bool operator==(const CFamilyItem &other) const 203 { 204 return itsName == other.itsName; 205 } 206 207 bool addFonts(const StyleCont &styles, bool sys); name()208 const QString &name() const 209 { 210 return itsName; 211 } fonts()212 const CFontItemCont &fonts() const 213 { 214 return itsFonts; 215 } 216 void addFont(CFontItem *font, bool update = true); 217 void removeFont(CFontItem *font, bool update); 218 void refresh(); 219 bool updateStatus(); 220 bool updateRegularFont(CFontItem *font); 221 CFontItem *findFont(quint32 style, bool sys); rowNumber()222 int rowNumber() const override 223 { 224 return itsParent.row(this); 225 } row(const CFontItem * font)226 int row(const CFontItem *font) const 227 { 228 return itsFonts.indexOf((CFontItem *)font); 229 } status()230 EStatus status() const 231 { 232 return itsStatus; 233 } realStatus()234 EStatus realStatus() const 235 { 236 return itsRealStatus; 237 } regularFont()238 CFontItem *regularFont() 239 { 240 return itsRegularFont; 241 } fontCount()242 int fontCount() const 243 { 244 return itsFontCount; 245 } 246 void getFoundries(QSet<QString> &foundries) const; slowUpdates()247 bool slowUpdates() const 248 { 249 return itsParent.slowUpdates(); 250 } 251 252 private: 253 bool usable(const CFontItem *font, bool root); 254 255 private: 256 QString itsName; 257 CFontItemCont itsFonts; 258 int itsFontCount; 259 EStatus itsStatus, itsRealStatus; 260 CFontItem *itsRegularFont; // 'RegularFont' is font nearest to 'Regular' style, and used for previews. 261 CFontList &itsParent; 262 }; 263 264 class CFontItem : public CFontModelItem 265 { 266 public: 267 CFontItem(CFontModelItem *p, const Style &s, bool sys); ~CFontItem()268 ~CFontItem() override 269 { 270 } 271 272 void refresh(); name()273 QString name() const 274 { 275 return family() + QString::fromLatin1(", ") + itsStyleName; 276 } isEnabled()277 bool isEnabled() const 278 { 279 return itsEnabled; 280 } isHidden()281 bool isHidden() const 282 { 283 return !itsEnabled; 284 } isBitmap()285 bool isBitmap() const 286 { 287 return !itsStyle.scalable(); 288 } fileName()289 const QString &fileName() const 290 { 291 return (*itsStyle.files().begin()).path(); 292 } style()293 const QString &style() const 294 { 295 return itsStyleName; 296 } styleInfo()297 quint32 styleInfo() const 298 { 299 return itsStyle.value(); 300 } index()301 int index() const 302 { 303 return (*itsStyle.files().begin()).index(); 304 } family()305 const QString &family() const 306 { 307 return (static_cast<CFamilyItem *>(parent()))->name(); 308 } rowNumber()309 int rowNumber() const override 310 { 311 return (static_cast<CFamilyItem *>(parent()))->row(this); 312 } files()313 const FileCont &files() const 314 { 315 return itsStyle.files(); 316 } writingSystems()317 qulonglong writingSystems() const 318 { 319 return itsStyle.writingSystems(); 320 } url()321 QUrl url() const 322 { 323 return CJobRunner::encode(family(), styleInfo(), isSystem()); 324 } removeFile(const File & f)325 void removeFile(const File &f) 326 { 327 itsStyle.remove(f); 328 } removeFiles(const FileCont & f)329 void removeFiles(const FileCont &f) 330 { 331 itsStyle.removeFiles(f); 332 } addFile(const File & f)333 void addFile(const File &f) 334 { 335 itsStyle.add(f); 336 } addFiles(const FileCont & f)337 void addFiles(const FileCont &f) 338 { 339 itsStyle.addFiles(f); 340 } 341 342 private: 343 QString itsStyleName; 344 Style itsStyle; 345 bool itsEnabled; 346 }; 347 348 class CFontListSortFilterProxy : public QSortFilterProxyModel 349 { 350 Q_OBJECT 351 352 public: 353 CFontListSortFilterProxy(QObject *parent, QAbstractItemModel *model); ~CFontListSortFilterProxy()354 ~CFontListSortFilterProxy() override 355 { 356 } 357 358 QVariant data(const QModelIndex &idx, int role) const override; 359 bool acceptFont(CFontItem *fnt, bool checkFontText) const; 360 bool acceptFamily(CFamilyItem *fam) const; 361 bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; 362 bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; 363 void setFilterGroup(CGroupListItem *grp); filterGroup()364 CGroupListItem *filterGroup() 365 { 366 return itsGroup; 367 } 368 369 void setFilterText(const QString &text); 370 void setFilterCriteria(CFontFilter::ECriteria crit, qulonglong ws, const QStringList &ft); 371 372 private Q_SLOTS: 373 374 void timeout(); 375 void fcResults(); 376 377 Q_SIGNALS: 378 379 void refresh(); 380 381 private: filterText()382 QString filterText() const 383 { 384 return CFontFilter::CRIT_FONTCONFIG == itsFilterCriteria ? (itsFcQuery ? itsFcQuery->font() : QString()) : itsFilterText; 385 } 386 387 private: 388 CGroupListItem *itsGroup; 389 QString itsFilterText; 390 CFontFilter::ECriteria itsFilterCriteria; 391 qulonglong itsFilterWs; 392 QStringList itsFilterTypes; 393 QTimer *itsTimer; 394 CFcQuery *itsFcQuery; 395 }; 396 397 class CFontListView : public QTreeView 398 { 399 Q_OBJECT 400 401 public: 402 CFontListView(QWidget *parent, CFontList *model); ~CFontListView()403 ~CFontListView() override 404 { 405 } 406 407 void getFonts(CJobRunner::ItemList &urls, QStringList &fontNames, QSet<Misc::TFont> *fonts, bool selected, bool getEnabled = true, bool getDisabled = true); 408 QSet<QString> getFiles(); 409 void getPrintableFonts(QSet<Misc::TFont> &items, bool selected); 410 void setFilterGroup(CGroupListItem *grp); 411 void stats(int &enabled, int &disabled, int &partial); 412 void selectedStatus(bool &enabled, bool &disabled); 413 QModelIndexList allFonts(); 414 void selectFirstFont(); 415 QModelIndexList getSelectedItems(); 416 417 Q_SIGNALS: 418 419 void del(); 420 void print(); 421 void enable(); 422 void disable(); 423 void fontsDropped(const QSet<QUrl> &); 424 void itemsSelected(const QModelIndexList &); 425 void refresh(); 426 void reload(); 427 428 public Q_SLOTS: 429 430 void listingPercent(int percent); 431 void refreshFilter(); 432 void filterText(const QString &text); 433 void filterCriteria(int crit, qulonglong ws, const QStringList &ft); 434 435 private Q_SLOTS: 436 437 void setSortColumn(int col); 438 void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) override; 439 void itemCollapsed(const QModelIndex &index); 440 void view(); 441 442 private: 443 QModelIndexList allIndexes(); 444 void startDrag(Qt::DropActions supportedActions) override; 445 void dragEnterEvent(QDragEnterEvent *event) override; 446 void dropEvent(QDropEvent *event) override; 447 void contextMenuEvent(QContextMenuEvent *ev) override; 448 bool viewportEvent(QEvent *event) override; 449 450 private: 451 CFontListSortFilterProxy *itsProxy; 452 CFontList *itsModel; 453 QMenu *itsMenu; 454 QAction *itsDeleteAct, *itsEnableAct, *itsDisableAct, *itsPrintAct, *itsViewAct; 455 bool itsAllowDrops; 456 }; 457 458 } 459