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"