File indexing completed on 2024-05-19 04:27:45

0001 /* This file is part of the KDE project
0002  * SPDX-FileCopyrightText: 2008 Jan Hambrecht <jaham@gmx.net>
0003  * SPDX-FileCopyrightText: 2018 Boudewijn Rempt <boud@valdyas.org>
0004  *
0005  * SPDX-License-Identifier: LGPL-2.0-or-later
0006  */
0007 
0008 
0009 #include <QPainter>
0010 #include <QDebug>
0011 #include <QStyledItemDelegate>
0012 
0013 #include "KisResourceItemDelegate.h"
0014 #include "KisResourceModel.h"
0015 #include <KisResourceThumbnailCache.h>
0016 #include <KoIcon.h>
0017 
0018 KisResourceItemDelegate::KisResourceItemDelegate(QObject *parent)
0019     : QAbstractItemDelegate(parent)
0020     , m_checkerPainter(4)
0021     , m_showText(false)
0022     , m_isWidget(false)
0023 {
0024 }
0025 
0026 void KisResourceItemDelegate::setShowText(bool showText)
0027 {
0028     m_showText = showText;
0029 }
0030 
0031 void KisResourceItemDelegate::setIsWidget(bool isWidget)
0032 {
0033     m_isWidget = isWidget;
0034 }
0035 
0036 void KisResourceItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem & option, const QModelIndex &index) const
0037 {
0038     if (!index.isValid()) return;
0039     painter->save();
0040     painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
0041     if (!(option.state & QStyle::State_Enabled)) {
0042         painter->setOpacity(0.2);
0043     }
0044 
0045     if (!index.isValid()) {
0046         painter->restore();
0047         return;
0048     }
0049 
0050     if (m_isWidget) {
0051 
0052         bool dirty = index.data(Qt::UserRole + KisAbstractResourceModel::Dirty).toBool();
0053         QIcon icon = qvariant_cast<QIcon>(index.data(Qt::DecorationRole));
0054 
0055         QImage preview;
0056         if (!icon.isNull()) {
0057             QSize iconSize = option.decorationSize; // or specify a desired size
0058             QPixmap pixmap = icon.pixmap(iconSize);
0059             preview = pixmap.toImage();
0060         }
0061 
0062         if (preview.isNull()) {
0063             preview = QImage(512, 512, QImage::Format_RGB32);
0064             preview.fill(Qt::red);
0065         }
0066 
0067         qreal devicePixelRatioF = painter->device()->devicePixelRatioF();
0068         QRect paintRect = option.rect.adjusted(1, 1, -1, -1);
0069 
0070         if (!m_showText) {
0071             QSize pixSize(paintRect.height(), paintRect.height());
0072 
0073             QSize size = pixSize * devicePixelRatioF;
0074             Qt::AspectRatioMode aspectMode = Qt::IgnoreAspectRatio;
0075             Qt::TransformationMode transformMode = Qt::SmoothTransformation;
0076             QImage previewHighDpi = preview.scaled(size, aspectMode, transformMode);
0077 
0078             previewHighDpi.setDevicePixelRatio(devicePixelRatioF);
0079             painter->drawImage(paintRect.x(), paintRect.y(), previewHighDpi);
0080         }
0081         else {
0082             QSize pixSize(paintRect.height(), paintRect.height());
0083 
0084             QSize size = pixSize * devicePixelRatioF;
0085             Qt::AspectRatioMode aspectMode = Qt::IgnoreAspectRatio;
0086             Qt::TransformationMode transformMode = Qt::SmoothTransformation;
0087             QImage previewHighDpi = preview.scaled(size, aspectMode, transformMode);
0088 
0089             previewHighDpi.setDevicePixelRatio(devicePixelRatioF);
0090             painter->drawImage(paintRect.x(), paintRect.y(), previewHighDpi);
0091 
0092             // Put an asterisk after the preset if it is dirty. This will help in case the pixmap icon is too small
0093 
0094             QString dirtyPresetIndicator = QString("");
0095             if (dirty) {
0096                 dirtyPresetIndicator = QString("*");
0097             }
0098 
0099             // QString presetDisplayName = index.data(Qt::UserRole + KisAbstractResourceModel::Name).toString().replace("_", " "); // don't need underscores that might be part of the file name
0100             QString presetDisplayName = index.data(Qt::DisplayRole).toString();
0101             painter->drawText(pixSize.width() + 10, option.rect.y() + option.rect.height() - 10, presetDisplayName.append(dirtyPresetIndicator));
0102         }
0103 
0104         if (dirty) {
0105             const QIcon icon = KisIconUtils::loadIcon("dirty-preset");
0106             QPixmap pixmap = icon.pixmap(QSize(16,16));
0107             painter->drawPixmap(paintRect.x() + 3, paintRect.y() + 3, pixmap);
0108         }
0109 
0110         if (option.state & QStyle::State_Selected) {
0111             painter->setCompositionMode(QPainter::CompositionMode_HardLight);
0112             painter->setOpacity(1.0);
0113             painter->fillRect(option.rect, option.palette.highlight());
0114 
0115             // highlight is not strong enough to pick out preset. draw border around it.
0116             painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
0117             painter->setPen(QPen(option.palette.highlight(), 4, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
0118             QRect selectedBorder = option.rect.adjusted(2 , 2, -2, -2); // constrict the rectangle so it doesn't bleed into other presets
0119             painter->drawRect(selectedBorder);
0120         }
0121         painter->restore();
0122         return;
0123 
0124     }
0125 
0126     bool dirty = index.data(Qt::UserRole + KisAbstractResourceModel::Dirty).toBool();
0127     QImage preview = KisResourceThumbnailCache::instance()->getImage(index);
0128 
0129     if (preview.isNull()) {
0130         preview = QImage(512, 512, QImage::Format_RGB32);
0131         preview.fill(Qt::red);
0132     }
0133 
0134     qreal devicePixelRatioF = painter->device()->devicePixelRatioF();
0135     QRect paintRect = option.rect.adjusted(1, 1, -1, -1);
0136 
0137     if (!m_showText) {
0138         QImage previewHighDpi =
0139             KisResourceThumbnailCache::instance()->getImage(index,
0140                                                              paintRect.size() * devicePixelRatioF,
0141                                                              Qt::IgnoreAspectRatio,
0142                                                              Qt::SmoothTransformation);
0143         previewHighDpi.setDevicePixelRatio(devicePixelRatioF);
0144 
0145         QImage destBackground(previewHighDpi.size(), QImage::Format_RGB32);
0146         destBackground.fill(Qt::white);
0147         destBackground.setDevicePixelRatio(devicePixelRatioF);
0148 
0149         painter->drawImage(paintRect.x(), paintRect.y(), destBackground);
0150         painter->drawImage(paintRect.x(), paintRect.y(), previewHighDpi);
0151     }
0152     else {
0153         QSize pixSize(paintRect.height(), paintRect.height());
0154         QImage previewHighDpi = KisResourceThumbnailCache::instance()->getImage(index,
0155                                                                                 pixSize * devicePixelRatioF,
0156                                                                                 Qt::IgnoreAspectRatio,
0157                                                                                 Qt::SmoothTransformation);
0158         previewHighDpi.setDevicePixelRatio(devicePixelRatioF);
0159 
0160         QImage destBackground(previewHighDpi.size(), QImage::Format_RGB32);
0161         destBackground.fill(Qt::white);
0162         destBackground.setDevicePixelRatio(devicePixelRatioF);
0163 
0164         painter->drawImage(paintRect.x(), paintRect.y(), destBackground);
0165         painter->drawImage(paintRect.x(), paintRect.y(), previewHighDpi);
0166 
0167         // Put an asterisk after the preset if it is dirty. This will help in case the pixmap icon is too small
0168 
0169         QString dirtyPresetIndicator = QString("");
0170         if (dirty) {
0171             dirtyPresetIndicator = QString("*");
0172         }
0173 
0174         QString presetDisplayName = index.data(Qt::UserRole + KisAbstractResourceModel::Name).toString().replace("_", " "); // don't need underscores that might be part of the file name
0175         painter->drawText(pixSize.width() + 10, option.rect.y() + option.rect.height() - 10, presetDisplayName.append(dirtyPresetIndicator));
0176     }
0177 
0178     if (dirty) {
0179         const QIcon icon = KisIconUtils::loadIcon("dirty-preset");
0180         QPixmap pixmap = icon.pixmap(QSize(16,16));
0181         painter->drawPixmap(paintRect.x() + 3, paintRect.y() + 3, pixmap);
0182     }
0183 
0184     if (option.state & QStyle::State_Selected) {
0185         painter->setCompositionMode(QPainter::CompositionMode_HardLight);
0186         painter->setOpacity(1.0);
0187         painter->fillRect(option.rect, option.palette.highlight());
0188 
0189         // highlight is not strong enough to pick out preset. draw border around it.
0190         painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
0191         painter->setPen(QPen(option.palette.highlight(), 4, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
0192         QRect selectedBorder = option.rect.adjusted(2 , 2, -2, -2); // constrict the rectangle so it doesn't bleed into other presets
0193         painter->drawRect(selectedBorder);
0194     }
0195     painter->restore();
0196 
0197 }
0198 
0199 
0200 QSize KisResourceItemDelegate::sizeHint(const QStyleOptionViewItem &optionItem, const QModelIndex &index) const
0201 {
0202     return optionItem.decorationSize;
0203 }