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 }