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 }