File indexing completed on 2024-06-02 05:43:53

0001 /*
0002     SPDX-FileCopyrightText: 2009 Craig Drummond <craig@kde.org>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "PreviewList.h"
0007 #include "Fc.h"
0008 #include "FcEngine.h"
0009 #include "FontList.h"
0010 #include <QApplication>
0011 #include <QContextMenuEvent>
0012 #include <QHeaderView>
0013 #include <QPainter>
0014 #include <QPixmapCache>
0015 #include <QStyledItemDelegate>
0016 #include <QTextStream>
0017 #include <private/qtx11extras_p.h>
0018 
0019 namespace KFI
0020 {
0021 static CFcEngine *theFcEngine = nullptr;
0022 
0023 CPreviewList::CPreviewList(QObject *parent)
0024     : QAbstractItemModel(parent)
0025 {
0026 }
0027 
0028 QVariant CPreviewList::data(const QModelIndex &index, int role) const
0029 {
0030     if (!index.isValid()) {
0031         return QVariant();
0032     }
0033 
0034     CPreviewListItem *item = static_cast<CPreviewListItem *>(index.internalPointer());
0035 
0036     if (item) {
0037         switch (role) {
0038         case Qt::DisplayRole:
0039             return FC::createName(item->name(), item->style());
0040         default:
0041             break;
0042         }
0043     }
0044     return QVariant();
0045 }
0046 
0047 Qt::ItemFlags CPreviewList::flags(const QModelIndex &) const
0048 {
0049     return Qt::ItemIsEnabled;
0050 }
0051 
0052 QModelIndex CPreviewList::index(int row, int column, const QModelIndex &parent) const
0053 {
0054     if (!parent.isValid()) {
0055         CPreviewListItem *item = m_items.value(row);
0056 
0057         if (item) {
0058             return createIndex(row, column, item);
0059         }
0060     }
0061 
0062     return QModelIndex();
0063 }
0064 
0065 QModelIndex CPreviewList::parent(const QModelIndex &) const
0066 {
0067     return QModelIndex();
0068 }
0069 
0070 void CPreviewList::clear()
0071 {
0072     Q_EMIT layoutAboutToBeChanged();
0073     qDeleteAll(m_items);
0074     m_items.clear();
0075     Q_EMIT layoutChanged();
0076 }
0077 
0078 void CPreviewList::showFonts(const QModelIndexList &fonts)
0079 {
0080     clear();
0081     Q_EMIT layoutAboutToBeChanged();
0082     QModelIndex index;
0083     foreach (index, fonts) {
0084         CFontModelItem *mi = static_cast<CFontModelItem *>(index.internalPointer());
0085         CFontItem *font = mi->parent() ? static_cast<CFontItem *>(mi) : (static_cast<CFamilyItem *>(mi))->regularFont();
0086 
0087         if (font) {
0088             m_items.append(new CPreviewListItem(font->family(), font->styleInfo(), font->isEnabled() ? QString() : font->fileName(), font->index()));
0089         }
0090     }
0091 
0092     Q_EMIT layoutChanged();
0093 }
0094 
0095 class CPreviewListViewDelegate : public QStyledItemDelegate
0096 {
0097 public:
0098     CPreviewListViewDelegate(QObject *p, int previewSize)
0099         : QStyledItemDelegate(p)
0100         , m_previewSize(previewSize)
0101     {
0102     }
0103     ~CPreviewListViewDelegate() override
0104     {
0105     }
0106 
0107     void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &idx) const override
0108     {
0109         CPreviewListItem *item = static_cast<CPreviewListItem *>(idx.internalPointer());
0110         QStyleOptionViewItem opt(option);
0111 
0112         opt.rect.adjust(1, constBorder - 3, 0, -(1 + m_previewSize));
0113 
0114         QStyledItemDelegate::paint(painter, opt, idx);
0115 
0116         opt.rect.adjust(constBorder, option.rect.height() - (1 + m_previewSize), -constBorder, 0);
0117         painter->save();
0118         painter->setPen(QApplication::palette().color(QPalette::Text));
0119         QRect lineRect(opt.rect.adjusted(-1, 3, 0, 2));
0120         painter->drawLine(lineRect.bottomLeft(), lineRect.bottomRight());
0121         painter->setClipRect(option.rect.adjusted(constBorder, 0, -constBorder, 0));
0122         painter->drawPixmap(opt.rect.topLeft(), getPixmap(item));
0123         painter->restore();
0124     }
0125 
0126     QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &idx) const override
0127     {
0128         QSize sz(QStyledItemDelegate::sizeHint(option, idx));
0129         // int   pWidth(getPixmap(static_cast<CPreviewListItem *>(idx.internalPointer())).width());
0130         int pWidth(1536);
0131 
0132         return QSize((constBorder * 2) + pWidth, sz.height() + 1 + constBorder + m_previewSize);
0133     }
0134 
0135     QPixmap getPixmap(CPreviewListItem *item) const
0136     {
0137         QString key;
0138         QPixmap pix;
0139         QColor text(QApplication::palette().color(QPalette::Text));
0140 
0141         QTextStream(&key) << "kfi-" << item->name() << "-" << item->style() << "-" << text.rgba();
0142 
0143         if (!QPixmapCache::find(key, &pix)) {
0144             QColor bgnd(Qt::black);
0145 
0146             bgnd.setAlpha(0);
0147             // TODO: Ideally, for this preview we want the fonts to be of a set point size
0148             pix = QPixmap::fromImage(
0149                 theFcEngine->drawPreview(item->file().isEmpty() ? item->name() : item->file(), item->style(), item->index(), text, bgnd, m_previewSize));
0150             QPixmapCache::insert(key, pix);
0151         }
0152 
0153         return pix;
0154     }
0155 
0156     int m_previewSize;
0157     static const int constBorder = 4;
0158 };
0159 
0160 CPreviewListView::CPreviewListView(CFcEngine *eng, QWidget *parent)
0161     : QTreeView(parent)
0162 {
0163     theFcEngine = eng;
0164 
0165     QFont font;
0166     int pixelSize((int)(((font.pointSizeF() * QX11Info::appDpiY()) / 72.0) + 0.5));
0167 
0168     m_model = new CPreviewList(this);
0169     setModel(m_model);
0170     setItemDelegate(new CPreviewListViewDelegate(this, (pixelSize + 12) * 3));
0171     setSelectionMode(NoSelection);
0172     setVerticalScrollMode(ScrollPerPixel);
0173     setSortingEnabled(false);
0174     setAlternatingRowColors(false);
0175     setAcceptDrops(false);
0176     setDragEnabled(false);
0177     header()->setVisible(false);
0178     setRootIsDecorated(false);
0179     resizeColumnToContents(0);
0180 }
0181 
0182 void CPreviewListView::refreshPreviews()
0183 {
0184     QPixmapCache::clear();
0185     repaint();
0186     resizeColumnToContents(0);
0187 }
0188 
0189 void CPreviewListView::showFonts(const QModelIndexList &fonts)
0190 {
0191     m_model->showFonts(fonts);
0192     resizeColumnToContents(0);
0193 }
0194 
0195 void CPreviewListView::contextMenuEvent(QContextMenuEvent *ev)
0196 {
0197     Q_EMIT showMenu(ev->pos());
0198 }
0199 
0200 }