File indexing completed on 2024-12-22 04:14:48
0001 /* 0002 * SPDX-FileCopyrightText: 2018 Anna Medonosova <anna.medonosova@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "KisGamutMaskChooser.h" 0008 0009 #include <QWidget> 0010 #include <QVBoxLayout> 0011 #include <QAbstractItemDelegate> 0012 #include <QMenu> 0013 #include <QActionGroup> 0014 #include <QFontMetrics> 0015 #include <QTextDocument> 0016 #include <QTextLayout> 0017 0018 #include <KisResourceItemChooser.h> 0019 #include <KisResourceItemListView.h> 0020 #include <KisResourceModel.h> 0021 #include <KisResourceThumbnailCache.h> 0022 #include <kis_icon_utils.h> 0023 #include <kis_config.h> 0024 #include "KisPopupButton.h" 0025 0026 /// The resource item delegate for rendering the resource preview 0027 class KisGamutMaskDelegate: public QAbstractItemDelegate 0028 { 0029 public: 0030 KisGamutMaskDelegate(QObject * parent = 0) : QAbstractItemDelegate(parent) 0031 , m_mode(KisGamutMaskChooser::ViewMode::THUMBNAIL) {} 0032 ~KisGamutMaskDelegate() override {} 0033 0034 /// reimplemented 0035 void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const override; 0036 0037 /// reimplemented 0038 QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex &) const override { 0039 return option.decorationSize; 0040 } 0041 0042 void setViewMode(KisGamutMaskChooser::ViewMode mode) { 0043 m_mode = mode; 0044 } 0045 0046 private: 0047 KisGamutMaskChooser::ViewMode m_mode; 0048 }; 0049 0050 void KisGamutMaskDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const 0051 { 0052 painter->save(); 0053 painter->setRenderHint(QPainter::SmoothPixmapTransform, true); 0054 0055 if (!index.isValid()) 0056 return; 0057 0058 QImage preview = index.data(Qt::UserRole + KisAbstractResourceModel::Thumbnail).value<QImage>(); 0059 QString name = index.data(Qt::UserRole + KisAbstractResourceModel::Name).value<QString>(); 0060 0061 if(preview.isNull()) { 0062 return; 0063 } 0064 0065 QRect paintRect = option.rect.adjusted(1, 1, -1, -1); 0066 0067 qreal devicePixelRatioF = painter->device()->devicePixelRatioF(); 0068 0069 if (m_mode == KisGamutMaskChooser::ViewMode::THUMBNAIL) { 0070 QImage previewHighDPI = 0071 KisResourceThumbnailCache::instance()->getImage(index, 0072 paintRect.size() * devicePixelRatioF, 0073 Qt::IgnoreAspectRatio, 0074 Qt::SmoothTransformation); 0075 previewHighDPI.setDevicePixelRatio(devicePixelRatioF); 0076 painter->drawImage(paintRect.x(), paintRect.y(), previewHighDPI); 0077 0078 if (option.state & QStyle::State_Selected) { 0079 painter->setCompositionMode(QPainter::CompositionMode_Overlay); 0080 painter->setOpacity(0.5); 0081 painter->fillRect(paintRect, Qt::white); 0082 painter->setCompositionMode(QPainter::CompositionMode_SourceOver); 0083 painter->setOpacity(1.0); 0084 painter->setPen(QPen(option.palette.highlight(), 2, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin)); 0085 QRect selectedBorder = option.rect.adjusted(1, 1, -1, -1); 0086 painter->drawRect(selectedBorder); 0087 } 0088 } else { 0089 QSize previewSize(paintRect.height(), paintRect.height()); 0090 0091 QImage previewHighDPI = 0092 KisResourceThumbnailCache::instance()->getImage(index, 0093 previewSize * devicePixelRatioF, 0094 Qt::IgnoreAspectRatio, 0095 Qt::SmoothTransformation); 0096 previewHighDPI.setDevicePixelRatio(devicePixelRatioF); 0097 0098 if (option.state & QStyle::State_Selected) { 0099 painter->setPen(QPen(option.palette.highlight(), 2.0)); 0100 painter->fillRect(option.rect, option.palette.highlight()); 0101 painter->setPen(option.palette.highlightedText().color()); 0102 } 0103 painter->drawImage(paintRect.x(), paintRect.y(), previewHighDPI); 0104 0105 int leftMargin = 8; 0106 int rightMargin = 7; 0107 int vertMargin = 4; 0108 int descOffset = 7; 0109 QFont font = option.font; 0110 font.setBold(true); 0111 painter->setFont(font); 0112 QRectF titleRect(QPointF(previewSize.width() + leftMargin, paintRect.y() + vertMargin), 0113 QPointF(paintRect.width() - rightMargin, paintRect.y() + descOffset + painter->fontMetrics().lineSpacing())); 0114 painter->drawText(titleRect, Qt::AlignLeft, 0115 painter->fontMetrics().elidedText( 0116 name, Qt::ElideRight, titleRect.width() 0117 ) 0118 ); 0119 QMap<QString, QVariant> metaData = index.data(Qt::UserRole + KisAbstractResourceModel::MetaData).value<QMap<QString, QVariant>>(); 0120 QString descriptionKey = "description"; 0121 QString description = metaData.contains(descriptionKey) ? metaData[descriptionKey].toString() : ""; 0122 if (!description.isEmpty() && !description.isNull()) { 0123 font.setPointSize(font.pointSize()-1); 0124 font.setBold(false); 0125 font.setStyle(QFont::StyleItalic); 0126 painter->setFont(font); 0127 QRectF descRect(QPointF(previewSize.width() + leftMargin, paintRect.y() + descOffset + painter->fontMetrics().lineSpacing()), 0128 QPointF(paintRect.right() - rightMargin, paintRect.bottom() - vertMargin)); 0129 0130 int numLines = floor(((float)descRect.height() / (float)painter->fontMetrics().lineSpacing())); 0131 if (numLines > 0) { 0132 int elideWidth = 0; 0133 QTextLayout textLayout(description); 0134 textLayout.beginLayout(); 0135 for (int i = 0; i < numLines; i++) { 0136 QTextLine line = textLayout.createLine(); 0137 if (line.isValid()) { 0138 line.setLineWidth(descRect.width()); 0139 elideWidth += line.naturalTextWidth(); 0140 } 0141 } 0142 0143 QString elidedText = painter->fontMetrics().elidedText(description, Qt::ElideRight, elideWidth); 0144 painter->drawText(descRect, Qt::AlignLeft|Qt::TextWordWrap, elidedText); 0145 } 0146 } 0147 } 0148 0149 painter->restore(); 0150 } 0151 0152 0153 KisGamutMaskChooser::KisGamutMaskChooser(QWidget *parent) : QWidget(parent) 0154 { 0155 m_delegate = new KisGamutMaskDelegate(this); 0156 0157 m_itemChooser = new KisResourceItemChooser(ResourceType::GamutMasks, false, this); 0158 m_itemChooser->setItemDelegate(m_delegate); 0159 m_itemChooser->showTaggingBar(true); 0160 m_itemChooser->showImportExportBtns(false); 0161 m_itemChooser->setSynced(true); 0162 0163 QVBoxLayout* layout = new QVBoxLayout(this); 0164 layout->setContentsMargins(0,0,0,0); 0165 0166 // TODO: menu for view mode change 0167 QMenu* menu = new QMenu(this); 0168 menu->setStyleSheet("margin: 6px"); 0169 menu->addSection(i18nc("@title Which elements to display (e.g., thumbnails or details)", "Display")); 0170 0171 QActionGroup *actionGroup = new QActionGroup(this); 0172 0173 KisConfig cfg(true); 0174 m_mode = KisGamutMaskChooser::ViewMode(cfg.readEntry<quint32>("GamutMasks.viewMode", KisGamutMaskChooser::THUMBNAIL)); 0175 0176 QAction* action = menu->addAction(KisIconUtils::loadIcon("view-preview"), 0177 i18n("Thumbnails"), this, SLOT(slotSetModeThumbnail())); 0178 action->setCheckable(true); 0179 action->setChecked(m_mode == KisGamutMaskChooser::THUMBNAIL); 0180 action->setActionGroup(actionGroup); 0181 0182 action = menu->addAction(KisIconUtils::loadIcon("view-list-details"), 0183 i18n("Details"), this, SLOT(slotSetModeDetail())); 0184 action->setCheckable(true); 0185 action->setChecked(m_mode == KisGamutMaskChooser::DETAIL); 0186 action->setActionGroup(actionGroup); 0187 0188 // setting the view mode 0189 setViewMode(m_mode); 0190 m_itemChooser->showViewModeBtn(true); 0191 KisPopupButton* viewModeButton = m_itemChooser->viewModeButton(); 0192 viewModeButton->setPopupWidget(menu); 0193 0194 layout->addWidget(m_itemChooser); 0195 0196 connect(m_itemChooser, SIGNAL(resourceSelected(KoResourceSP )), this, SLOT(resourceSelected(KoResourceSP ))); 0197 } 0198 0199 KisGamutMaskChooser::~KisGamutMaskChooser() 0200 { 0201 0202 } 0203 0204 void KisGamutMaskChooser::setCurrentResource(KoResourceSP resource) 0205 { 0206 m_itemChooser->setCurrentResource(resource); 0207 } 0208 0209 void KisGamutMaskChooser::resizeEvent(QResizeEvent *event) 0210 { 0211 QWidget::resizeEvent(event); 0212 updateViewSettings(); 0213 } 0214 0215 void KisGamutMaskChooser::setViewMode(KisGamutMaskChooser::ViewMode mode) 0216 { 0217 m_mode = mode; 0218 updateViewSettings(); 0219 } 0220 0221 void KisGamutMaskChooser::updateViewSettings() 0222 { 0223 KisConfig cfg(false); 0224 cfg.writeEntry("GamutMasks.viewMode", qint32(m_mode)); 0225 0226 if (m_mode == KisGamutMaskChooser::THUMBNAIL) { 0227 m_itemChooser->setListViewMode(ListViewMode::IconGrid); 0228 m_itemChooser->setRowHeight(this->fontMetrics().lineSpacing() * 4); 0229 m_itemChooser->setColumnWidth(this->fontMetrics().lineSpacing() * 4); 0230 m_delegate->setViewMode(m_mode); 0231 } 0232 else if (m_mode == KisGamutMaskChooser::DETAIL) { 0233 m_itemChooser->setListViewMode(ListViewMode::Detail); 0234 m_itemChooser->setRowHeight(this->fontMetrics().lineSpacing()*4); 0235 m_delegate->setViewMode(m_mode); 0236 } 0237 } 0238 0239 void KisGamutMaskChooser::resourceSelected(KoResourceSP resource) 0240 { 0241 emit sigGamutMaskSelected(resource.staticCast<KoGamutMask>()); 0242 } 0243 0244 void KisGamutMaskChooser::slotSetModeThumbnail() 0245 { 0246 setViewMode(KisGamutMaskChooser::THUMBNAIL); 0247 } 0248 0249 void KisGamutMaskChooser::slotSetModeDetail() 0250 { 0251 setViewMode(KisGamutMaskChooser::DETAIL); 0252 }