File indexing completed on 2024-05-19 04:29:28

0001 /*
0002  *  SPDX-FileCopyrightText: 2018 Michael Zhou <simeirxh@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 // Qt
0008 #include <QPainter>
0009 #include <QPen>
0010 #include <QVector>
0011 #include <QCompleter>
0012 
0013 // STL
0014 #include <algorithm>
0015 
0016 #include "kis_palette_view.h"
0017 #include "KisPaletteComboBox.h"
0018 
0019 KisPaletteComboBox::KisPaletteComboBox(QWidget *parent)
0020     : KisSqueezedComboBox(parent)
0021     , m_model(0)
0022 {
0023     setEditable(true);
0024     setInsertPolicy(NoInsert);
0025     completer()->setCompletionMode(QCompleter::PopupCompletion);
0026     completer()->setCaseSensitivity(Qt::CaseInsensitive);
0027     completer()->setFilterMode(Qt::MatchContains);
0028     connect(this, SIGNAL(currentIndexChanged(int)), SLOT(slotIndexUpdated(int)));
0029 }
0030 
0031 KisPaletteComboBox::~KisPaletteComboBox()
0032 { }
0033 
0034 void KisPaletteComboBox::setPaletteModel(const KisPaletteModel *paletteModel)
0035 {
0036     if (!m_model.isNull()) {
0037         m_model->disconnect(this);
0038     }
0039     m_model = paletteModel;
0040     if (m_model.isNull()) { return; }
0041     slotPaletteChanged();
0042     connect(m_model, SIGNAL(sigPaletteChanged()), SLOT(slotPaletteChanged()));
0043     connect(m_model, SIGNAL(sigPaletteModified()), SLOT(slotPaletteChanged()));
0044 }
0045 
0046 void KisPaletteComboBox::setCompanionView(KisPaletteView *view)
0047 {
0048     if (!m_view.isNull()) {
0049         m_view->disconnect(this);
0050         disconnect(m_view.data());
0051     }
0052     m_view = view;
0053     setPaletteModel(view->paletteModel());
0054     connect(view, SIGNAL(sigIndexSelected(QModelIndex)), SLOT(slotSwatchSelected(QModelIndex)));
0055 }
0056 
0057 void KisPaletteComboBox::slotPaletteChanged()
0058 {
0059     clear();
0060     m_groupMapMap.clear();
0061     m_idxSwatchMap.clear();
0062 
0063     if (QSharedPointer<KoColorSet>(m_model->colorSet()).isNull()) { return; }
0064 
0065     for (const QString &groupName : m_model->colorSet()->swatchGroupNames()) {
0066         QVector<KisSwatchGroup::SwatchInfo> infoList;
0067         PosIdxMapType posIdxMap;
0068         const KisSwatchGroupSP group = m_model->colorSet()->getGroup(groupName);
0069         for (const KisSwatchGroup::SwatchInfo &info : group->infoList()) {
0070             infoList.append(info);
0071         }
0072         std::sort(infoList.begin(), infoList.end(), swatchInfoLess);
0073         for (const KisSwatchGroup::SwatchInfo &info : infoList) {
0074             const KisSwatch &swatch = info.swatch;
0075             QString name = swatch.name();
0076             if (!swatch.id().isEmpty()){
0077                 name = swatch.id() + " - " + swatch.name();
0078             }
0079             addSqueezedItem(QIcon(createColorSquare(swatch)), name);
0080             posIdxMap[SwatchPosType(info.column, info.row)] = count() - 1;
0081             m_idxSwatchMap.push_back(swatch);
0082         }
0083         m_groupMapMap[group->name()] = posIdxMap;
0084     }
0085     if (m_view.isNull()) {
0086         setCurrentIndex(0);
0087     }
0088     QModelIndex idx = m_view->currentIndex();
0089     if (!idx.isValid()) { return; }
0090     if (qvariant_cast<bool>(idx.data(KisPaletteModel::IsGroupNameRole))) { return; }
0091     if (!qvariant_cast<bool>(idx.data(KisPaletteModel::CheckSlotRole))) { return; }
0092 
0093     blockSignals(true); // this is a passive selection; this shouldn't make others change
0094     slotSwatchSelected(idx);
0095     blockSignals(false);
0096 }
0097 
0098 bool KisPaletteComboBox::swatchInfoLess(const KisSwatchGroup::SwatchInfo &first, const KisSwatchGroup::SwatchInfo &second)
0099 {
0100     return first.swatch.name() < second.swatch.name();
0101 }
0102 
0103 QPixmap KisPaletteComboBox::createColorSquare(const KisSwatch &swatch) const
0104 {
0105     QPixmap colorSquare(32, 32);
0106     if (swatch.spotColor()) {
0107         QImage img = QImage(32, 32, QImage::Format_ARGB32);
0108         QPainter circlePainter;
0109         img.fill(Qt::transparent);
0110         circlePainter.begin(&img);
0111         QBrush brush = QBrush(Qt::SolidPattern);
0112         brush.setColor(swatch.color().toQColor());
0113         circlePainter.setBrush(brush);
0114         QPen pen = circlePainter.pen();
0115         pen.setColor(Qt::transparent);
0116         pen.setWidth(0);
0117         circlePainter.setPen(pen);
0118         circlePainter.drawEllipse(0, 0, 32, 32);
0119         circlePainter.end();
0120         colorSquare = QPixmap::fromImage(img);
0121     } else {
0122         colorSquare.fill(swatch.color().toQColor());
0123     }
0124     return colorSquare;
0125 }
0126 
0127 void KisPaletteComboBox::slotSwatchSelected(const QModelIndex &index)
0128 {
0129     if (!qvariant_cast<bool>(index.data(KisPaletteModel::CheckSlotRole))) {
0130         return;
0131     }
0132     if (qvariant_cast<bool>(index.data(KisPaletteModel::IsGroupNameRole))) {
0133         return;
0134     }
0135     QString gName = qvariant_cast<QString>(index.data(KisPaletteModel::GroupNameRole));
0136     int rowInGroup = qvariant_cast<int>(index.data(KisPaletteModel::RowInGroupRole));
0137     setCurrentIndex(m_groupMapMap[gName][SwatchPosType(index.column(), rowInGroup)]);
0138 }
0139 
0140 void KisPaletteComboBox::slotIndexUpdated(int idx)
0141 {
0142     if (idx >= 0 && idx < m_idxSwatchMap.size()) {
0143         emit sigColorSelected(m_idxSwatchMap[idx].color());
0144     }
0145 }