File indexing completed on 2024-12-22 04:14:47

0001 /*
0002  *  SPDX-FileCopyrightText: 2011 Sven Langkamp <sven.langkamp@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 
0007 #include "channelmodel.h"
0008 #include <QImage>
0009 #include <KoColorSpace.h>
0010 #include <KoChannelInfo.h>
0011 #include <KoColorModelStandardIds.h>
0012 
0013 #include <kis_painter.h>
0014 
0015 #include <kis_group_layer.h>
0016 #include <kis_paint_device.h>
0017 #include <kis_iterator_ng.h>
0018 #include <kis_default_bounds.h>
0019 
0020 #include <kis_canvas2.h>
0021 
0022 ChannelModel::ChannelModel(QObject* parent):
0023     QAbstractTableModel(parent),
0024     m_canvas(nullptr),
0025     m_oversampleRatio(2),
0026     m_channelCount(0)
0027 {
0028     setThumbnailSizeLimit(QSize(64, 64));
0029 }
0030 
0031 ChannelModel::~ChannelModel()
0032 {
0033 }
0034 
0035 QVariant ChannelModel::data(const QModelIndex& index, int role) const
0036 {
0037     if (m_canvas && m_canvas->image() && index.isValid()) {
0038         KisGroupLayerSP rootLayer = m_canvas->image()->rootLayer();
0039         const KoColorSpace *cs = rootLayer->colorSpace();
0040         if (cs->channelCount() != m_channelCount) return QVariant();
0041 
0042         const QList<KoChannelInfo*> channels = cs->channels();
0043 
0044         int channelIndex = index.row();
0045 
0046         if (index.row() < cs->channelCount()) {
0047 
0048             switch (role) {
0049             case Qt::DisplayRole: {
0050                 if (index.column() == 2) {
0051                     return channels.at(channelIndex)->name();
0052                 }
0053                 return QVariant();
0054             }
0055             case Qt::DecorationRole: {
0056                 if (index.column() == 1 &&
0057                         !m_thumbnails.isEmpty() &&
0058                         index.row() < m_thumbnails.size()) {
0059 
0060                     return QVariant(m_thumbnails.at(index.row()));
0061                 }
0062                 return QVariant();
0063             }
0064             case Qt::CheckStateRole: {
0065                 Q_ASSERT(index.row() < rowCount());
0066                 Q_ASSERT(index.column() < columnCount());
0067 
0068                 if (index.column() == 0) {
0069                     QBitArray flags = rootLayer->channelFlags();
0070                     return (flags.isEmpty() || flags.testBit(channelIndex)) ? Qt::Checked : Qt::Unchecked;
0071                 }
0072                 return QVariant();
0073             }
0074             }
0075         }
0076     }
0077     return QVariant();
0078 }
0079 
0080 QVariant ChannelModel::headerData(int section, Qt::Orientation orientation, int role) const
0081 {
0082     Q_UNUSED(section); Q_UNUSED(orientation); Q_UNUSED(role);
0083     return QVariant();
0084 }
0085 
0086 int ChannelModel::rowCount(const QModelIndex& /*parent*/) const
0087 {
0088     if (!m_canvas || !m_canvas->image()) return 0;
0089 
0090     return m_channelCount;
0091 }
0092 
0093 int ChannelModel::columnCount(const QModelIndex& /*parent*/) const
0094 {
0095     if (!m_canvas) return 0;
0096 
0097     //columns are: checkbox, thumbnail, channel name
0098     return 3;
0099 }
0100 
0101 bool ChannelModel::setData(const QModelIndex& index, const QVariant& value, int role)
0102 {
0103     if (m_canvas && m_canvas->image()) {
0104         KisGroupLayerSP rootLayer = m_canvas->image()->rootLayer();
0105         const KoColorSpace *cs = rootLayer->colorSpace();
0106         if (cs->channelCount() != m_channelCount) return false;
0107 
0108         const QList<KoChannelInfo*> channels = cs->channels();
0109         KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(index.row() <= channels.count(), false);
0110 
0111         int channelIndex = index.row();
0112 
0113         if (role == Qt::CheckStateRole) {
0114             QBitArray flags = rootLayer->channelFlags();
0115             flags = flags.isEmpty() ? cs->channelFlags(true, true) : flags;
0116             Q_ASSERT(!flags.isEmpty());
0117 
0118             flags.setBit(channelIndex, value.toInt() == Qt::Checked);
0119             rootLayer->setChannelFlags(flags);
0120 
0121             emit channelFlagsChanged();
0122             emit dataChanged(this->index(0, 0), this->index(channels.count(), 0));
0123             return true;
0124         }
0125     }
0126     return false;
0127 }
0128 
0129 //User double clicked on a row (but on channel checkbox)
0130 //we select this channel, and deselect all other channels (except alpha, which we don't touch)
0131 //this makes it fast to select single color channel
0132 void ChannelModel::rowActivated(const QModelIndex &index)
0133 {
0134     if (m_canvas && m_canvas->image()) {
0135         KisGroupLayerWSP rootLayer = m_canvas->image()->rootLayer();
0136         const KoColorSpace* cs = rootLayer->colorSpace();
0137         if (cs->channelCount() != m_channelCount) return;
0138 
0139         const QList<KoChannelInfo*> channels = cs->channels();
0140         Q_ASSERT(index.row() <= channels.count());
0141 
0142         int channelIndex = index.row();
0143 
0144         QBitArray flags = rootLayer->channelFlags();
0145         flags = flags.isEmpty() ? cs->channelFlags(true, true) : flags;
0146         Q_ASSERT(!flags.isEmpty());
0147 
0148         for (int i = 0; i < channels.count(); ++i) {
0149             if (channels[i]->channelType() != KoChannelInfo::ALPHA) {
0150                 flags.setBit(i, (i == channelIndex));
0151             }
0152         }
0153 
0154         rootLayer->setChannelFlags(flags);
0155 
0156         emit channelFlagsChanged();
0157         emit dataChanged(this->index(0, 0), this->index(channels.count(), 0));
0158     }
0159 }
0160 
0161 Qt::ItemFlags ChannelModel::flags(const QModelIndex& /*index*/) const
0162 {
0163     Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
0164     return flags;
0165 }
0166 
0167 void ChannelModel::setCanvas(KisCanvas2 *canvas)
0168 {
0169     m_canvasConnections.clear();
0170 
0171     m_canvas = canvas;
0172 
0173     if (m_canvas) {
0174         m_canvasConnections.addConnection(m_canvas->image(),
0175                                           SIGNAL(sigColorSpaceChanged(const KoColorSpace*)),
0176                                           this,
0177                                           SLOT(slotColorSpaceChanged(const KoColorSpace*)));
0178     }
0179 }
0180 
0181 void ChannelModel::setChannelThumbnails(const QVector<QImage> &channels, const KoColorSpace *cs)
0182 {
0183     if (m_canvas) {
0184         KisGroupLayerWSP rootLayer = m_canvas->image()->rootLayer();
0185 
0186         if (!cs || *rootLayer->colorSpace() == *cs) {
0187             const int newChannelCount = cs ? cs->channelCount() : 0;
0188 
0189 
0190             if (newChannelCount != m_channelCount) {
0191                 beginResetModel();
0192                 m_thumbnails = channels;
0193                 m_channelCount = newChannelCount;
0194                 endResetModel();
0195             } else {
0196                 m_thumbnails = channels;
0197                 emit dataChanged(this->index(0, 0), this->index(channels.count(), this->columnCount()));
0198             }
0199         }
0200     }
0201 }
0202 
0203 void ChannelModel::slotColorSpaceChanged(const KoColorSpace *colorSpace)
0204 {
0205     setChannelThumbnails({}, colorSpace);
0206 }
0207 
0208 void ChannelModel::setThumbnailSizeLimit(QSize size)
0209 {
0210     m_thumbnailSizeLimit = size;
0211 }
0212 
0213 QSize ChannelModel::thumbnailSizeLimit() const
0214 {
0215     return m_thumbnailSizeLimit;
0216 }
0217 
0218 #include "moc_channelmodel.cpp"