File indexing completed on 2024-05-12 16:02:03

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()),
0043             SLOT(slotPaletteChanged()));
0044     connect(m_model, SIGNAL(sigPaletteModified()),
0045             SLOT(slotPaletteChanged()));
0046 }
0047 
0048 void KisPaletteComboBox::setCompanionView(KisPaletteView *view)
0049 {
0050     if (!m_view.isNull()) {
0051         m_view->disconnect(this);
0052         disconnect(m_view.data());
0053     }
0054     m_view = view;
0055     setPaletteModel(view->paletteModel());
0056     connect(view, SIGNAL(sigIndexSelected(QModelIndex)),
0057             SLOT(slotSwatchSelected(QModelIndex)));
0058 }
0059 
0060 void KisPaletteComboBox::slotPaletteChanged()
0061 {
0062     clear();
0063     m_groupMapMap.clear();
0064     m_idxSwatchMap.clear();
0065 
0066     if (QSharedPointer<KoColorSet>(m_model->colorSet()).isNull()) { return; }
0067 
0068     for (const QString &groupName : m_model->colorSet()->getGroupNames()) {
0069         QVector<SwatchInfoType> infoList;
0070         PosIdxMapType posIdxMap;
0071         const KisSwatchGroup *group = m_model->colorSet()->getGroup(groupName);
0072         for (const SwatchInfoType &info : group->infoList()) {
0073             infoList.append(info);
0074         }
0075         std::sort(infoList.begin(), infoList.end(), swatchInfoLess);
0076         for (const SwatchInfoType &info : infoList) {
0077             const KisSwatch &swatch = info.swatch;
0078             QString name = swatch.name();
0079             if (!swatch.id().isEmpty()){
0080                 name = swatch.id() + " - " + swatch.name();
0081             }
0082             addSqueezedItem(QIcon(createColorSquare(swatch)), name);
0083             posIdxMap[SwatchPosType(info.column, info.row)] = count() - 1;
0084             m_idxSwatchMap.push_back(swatch);
0085         }
0086         m_groupMapMap[group->name()] = posIdxMap;
0087     }
0088     if (m_view.isNull()) {
0089         setCurrentIndex(0);
0090     }
0091     QModelIndex idx = m_view->currentIndex();
0092     if (!idx.isValid()) { return; }
0093     if (qvariant_cast<bool>(idx.data(KisPaletteModel::IsGroupNameRole))) { return; }
0094     if (!qvariant_cast<bool>(idx.data(KisPaletteModel::CheckSlotRole))) { return; }
0095 
0096     blockSignals(true); // this is a passive selection; this shouldn't make others change
0097     slotSwatchSelected(idx);
0098     blockSignals(false);
0099 }
0100 
0101 bool KisPaletteComboBox::swatchInfoLess(const SwatchInfoType &first, const SwatchInfoType &second)
0102 {
0103     return first.swatch.name() < second.swatch.name();
0104 }
0105 
0106 QPixmap KisPaletteComboBox::createColorSquare(const KisSwatch &swatch) const
0107 {
0108     QPixmap colorSquare(32, 32);
0109     if (swatch.spotColor()) {
0110         QImage img = QImage(32, 32, QImage::Format_ARGB32);
0111         QPainter circlePainter;
0112         img.fill(Qt::transparent);
0113         circlePainter.begin(&img);
0114         QBrush brush = QBrush(Qt::SolidPattern);
0115         brush.setColor(swatch.color().toQColor());
0116         circlePainter.setBrush(brush);
0117         QPen pen = circlePainter.pen();
0118         pen.setColor(Qt::transparent);
0119         pen.setWidth(0);
0120         circlePainter.setPen(pen);
0121         circlePainter.drawEllipse(0, 0, 32, 32);
0122         circlePainter.end();
0123         colorSquare = QPixmap::fromImage(img);
0124     } else {
0125         colorSquare.fill(swatch.color().toQColor());
0126     }
0127     return colorSquare;
0128 }
0129 
0130 void KisPaletteComboBox::slotSwatchSelected(const QModelIndex &index)
0131 {
0132     if (!qvariant_cast<bool>(index.data(KisPaletteModel::CheckSlotRole))) {
0133         return;
0134     }
0135     if (qvariant_cast<bool>(index.data(KisPaletteModel::IsGroupNameRole))) {
0136         return;
0137     }
0138     QString gName = qvariant_cast<QString>(index.data(KisPaletteModel::GroupNameRole));
0139     int rowInGroup = qvariant_cast<int>(index.data(KisPaletteModel::RowInGroupRole));
0140     setCurrentIndex(m_groupMapMap[gName][SwatchPosType(index.column(), rowInGroup)]);
0141 }
0142 
0143 void KisPaletteComboBox::slotIndexUpdated(int idx)
0144 {
0145     if (idx >= 0 && idx < m_idxSwatchMap.size()) {
0146         emit sigColorSelected(m_idxSwatchMap[idx].color());
0147     }
0148 }