File indexing completed on 2024-12-22 04:14:40
0001 /* 0002 * SPDX-FileCopyrightText: 2016 Jouni Pentikäinen <joupent@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "KisAnimCurvesChannelsModel.h" 0008 0009 #include "KisAnimCurvesModel.h" 0010 #include "kis_dummies_facade_base.h" 0011 #include "kis_node_dummies_graph.h" 0012 #include "kis_node.h" 0013 #include "kis_node_view_color_scheme.h" 0014 #include "kis_scalar_keyframe_channel.h" 0015 #include "kis_signal_auto_connection.h" 0016 #include <kis_painting_tweaks.h> 0017 #include "kis_image.h" 0018 #include "KisAnimUtils.h" 0019 0020 #include <QApplication> 0021 0022 const quintptr ID_NODE = 0xffffffff; 0023 0024 struct NodeListItem 0025 { 0026 NodeListItem(KisNodeDummy *dummy) 0027 : dummy(dummy) 0028 {} 0029 0030 KisNodeDummy *dummy; 0031 QList<KisAnimationCurve*> curves; 0032 }; 0033 0034 struct KisAnimCurvesChannelsModel::Private 0035 { 0036 KisAnimCurvesModel *curvesModel; 0037 KisDummiesFacadeBase *dummiesFacade = 0; 0038 KisSignalAutoConnectionsStore dummiesFacadeConnections; 0039 0040 QList<NodeListItem*> items; 0041 0042 Private(KisAnimCurvesModel *curvesModel) 0043 : curvesModel(curvesModel) 0044 {} 0045 0046 NodeListItem * itemForRow(int row) { 0047 if (row < 0 || row >= items.count()) 0048 return nullptr; 0049 return items.at(row); 0050 } 0051 0052 int rowForDummy(KisNodeDummy *dummy) { 0053 for (int row=0; row < items.count(); row++) { 0054 if (items.at(row)->dummy == dummy) return row; 0055 } 0056 0057 return -1; 0058 } 0059 0060 void addCurveForChannel(NodeListItem *nodeItem, KisKeyframeChannel *channel) { 0061 KisScalarKeyframeChannel *scalarChannel = dynamic_cast<KisScalarKeyframeChannel*>(channel); 0062 0063 if (scalarChannel) { 0064 KisAnimationCurve *curve = curvesModel->addCurve(scalarChannel); 0065 nodeItem->curves.append(curve); 0066 } 0067 } 0068 }; 0069 0070 KisAnimCurvesChannelsModel::KisAnimCurvesChannelsModel(KisAnimCurvesModel *curvesModel, QObject *parent) 0071 : QAbstractItemModel(parent) 0072 , m_d(new Private(curvesModel)) 0073 {} 0074 0075 KisAnimCurvesChannelsModel::~KisAnimCurvesChannelsModel() 0076 { 0077 qDeleteAll(m_d->items); 0078 m_d->items.clear(); 0079 } 0080 0081 void KisAnimCurvesChannelsModel::setDummiesFacade(KisDummiesFacadeBase *facade) 0082 { 0083 m_d->dummiesFacadeConnections.clear(); 0084 m_d->dummiesFacade = facade; 0085 m_d->dummiesFacadeConnections.addConnection(m_d->dummiesFacade, SIGNAL(sigBeginRemoveDummy(KisNodeDummy*)), 0086 this, SLOT(slotNotifyDummyRemoved(KisNodeDummy*))); 0087 } 0088 0089 void KisAnimCurvesChannelsModel::selectedNodesChanged(const KisNodeList &nodes) 0090 { 0091 // Remove unselected nodes 0092 for (int i = m_d->items.count()-1; i >= 0; i--) { 0093 NodeListItem *item = m_d->items.at(i); 0094 if (item && item->dummy) { 0095 if (!nodes.contains(item->dummy->node())) { 0096 beginRemoveRows(QModelIndex(), i, i); 0097 m_d->items.removeAt(i); 0098 endRemoveRows(); 0099 0100 Q_FOREACH(KisAnimationCurve *curve, item->curves) { 0101 m_d->curvesModel->removeCurve(curve); 0102 0103 } 0104 0105 if (!item->dummy->node().isNull()) { 0106 item->dummy->node()->disconnect(this); 0107 } 0108 0109 delete item; 0110 } 0111 } 0112 } 0113 0114 // Add newly selected nodes 0115 Q_FOREACH(KisNodeSP node, nodes) { 0116 KisNodeDummy *dummy = m_d->dummiesFacade->dummyForNode(node); 0117 if (!dummy) continue; 0118 0119 if (m_d->rowForDummy(dummy) == -1) { 0120 beginInsertRows(QModelIndex(), m_d->items.count(), m_d->items.count()); 0121 0122 NodeListItem *item = new NodeListItem(dummy); 0123 m_d->items.append(item); 0124 0125 Q_FOREACH(KisKeyframeChannel *channel, dummy->node()->keyframeChannels()) { 0126 m_d->addCurveForChannel(item, channel); 0127 } 0128 0129 connect(node.data(), &KisNode::keyframeChannelAdded, 0130 this, &KisAnimCurvesChannelsModel::keyframeChannelAddedToNode); 0131 0132 endInsertRows(); 0133 } 0134 } 0135 } 0136 0137 void KisAnimCurvesChannelsModel::reset(const QModelIndex &index) 0138 { 0139 const quintptr parentRow = index.internalId(); 0140 const bool indexIsNode = (parentRow == ID_NODE); 0141 0142 if (indexIsNode) { 0143 NodeListItem *item = m_d->itemForRow(index.row()); 0144 0145 KisNodeSP node = item->dummy->node(); 0146 if (!node || !node->image()) 0147 return; 0148 0149 KisImageSP image = node->image().toStrongRef(); 0150 0151 QList<KisAnimationCurve*> curves = item->curves; 0152 QList<QString> ids; 0153 Q_FOREACH( const KisAnimationCurve* curve, curves ) { 0154 ids << curve->channel()->id(); 0155 } 0156 0157 KisAnimUtils::resetChannels(image, node, ids); 0158 0159 } else { 0160 NodeListItem *item = m_d->itemForRow(parentRow); 0161 0162 KisAnimationCurve* curve = item->curves.at(index.row()); 0163 0164 if (!curve) 0165 return; 0166 0167 KisNodeSP node = item->dummy->node(); 0168 0169 if (!node || !node->image()) 0170 return; 0171 0172 KisImageSP image = node->image().toStrongRef(); 0173 KisAnimUtils::resetChannel(image, node, curve->channel()->id()); 0174 } 0175 } 0176 0177 void KisAnimCurvesChannelsModel::keyframeChannelAddedToNode(KisKeyframeChannel *channel) 0178 { 0179 KisNodeDummy *dummy = m_d->dummiesFacade->dummyForNode(KisNodeSP(channel->node())); 0180 int row = m_d->rowForDummy(dummy); 0181 KIS_ASSERT_RECOVER_RETURN(row >= 0); 0182 0183 NodeListItem *item = m_d->itemForRow(row); 0184 0185 int newCurveRow = item->curves.count(); 0186 beginInsertRows(index(row, 0, QModelIndex()), newCurveRow, newCurveRow); 0187 0188 m_d->addCurveForChannel(item, channel); 0189 0190 endInsertRows(); 0191 } 0192 0193 void KisAnimCurvesChannelsModel::slotNotifyDummyRemoved(KisNodeDummy *dummy) 0194 { 0195 bool shouldChangeSelection = false; 0196 KisNodeList newSelectedNodes; 0197 0198 Q_FOREACH (NodeListItem *item, m_d->items) { 0199 if (item->dummy == dummy) { 0200 shouldChangeSelection = true; 0201 break; 0202 } 0203 0204 newSelectedNodes << item->dummy->node(); 0205 } 0206 0207 if (shouldChangeSelection) { 0208 selectedNodesChanged(newSelectedNodes); 0209 } 0210 } 0211 0212 QModelIndex KisAnimCurvesChannelsModel::index(int row, int column, const QModelIndex &parent) const 0213 { 0214 Q_UNUSED(column); 0215 0216 if (!parent.isValid()) { 0217 // Node 0218 0219 NodeListItem *item = m_d->itemForRow(row); 0220 if (!item) return QModelIndex(); 0221 0222 return createIndex(row, column, ID_NODE); 0223 } else { 0224 // Channel 0225 if (parent.parent().isValid()) return QModelIndex(); 0226 0227 NodeListItem *parentItem = m_d->itemForRow(parent.row()); 0228 if (!parentItem) return QModelIndex(); 0229 0230 if (row >= parentItem->curves.count()) return QModelIndex(); 0231 0232 return createIndex(row, column, parent.row()); 0233 } 0234 } 0235 0236 QModelIndex KisAnimCurvesChannelsModel::parent(const QModelIndex &child) const 0237 { 0238 quintptr parentIndex = child.internalId(); 0239 if (parentIndex == ID_NODE) return QModelIndex(); 0240 return createIndex(parentIndex, 0, ID_NODE); 0241 } 0242 0243 int KisAnimCurvesChannelsModel::rowCount(const QModelIndex &parent) const 0244 { 0245 if (!parent.isValid()) { 0246 // Root 0247 return m_d->items.count(); 0248 } else if (parent.internalId() == ID_NODE) { 0249 // Node 0250 NodeListItem *item = m_d->itemForRow(parent.row()); 0251 return item->curves.count(); 0252 } else { 0253 // Channel 0254 return 0; 0255 } 0256 } 0257 0258 int KisAnimCurvesChannelsModel::columnCount(const QModelIndex &parent) const 0259 { 0260 Q_UNUSED(parent); 0261 return 1; 0262 } 0263 0264 QVariant KisAnimCurvesChannelsModel::data(const QModelIndex &index, int role) const 0265 { 0266 const quintptr parentRow = index.internalId(); 0267 const bool indexIsNode = (parentRow == ID_NODE); 0268 NodeListItem *item = m_d->itemForRow(indexIsNode ? index.row() : parentRow); 0269 0270 switch (role) { 0271 case Qt::DisplayRole: { 0272 if (indexIsNode) { 0273 return item->dummy->node()->name(); 0274 } else { 0275 KisKeyframeChannel *channel = item->curves.at(index.row())->channel(); 0276 return channel->name(); 0277 } 0278 } break; 0279 0280 case CurveRole: 0281 return !indexIsNode; 0282 0283 case CurveColorRole: 0284 return indexIsNode ? QVariant() : item->curves.at(index.row())->color(); 0285 0286 case CurveVisibilityRole: 0287 return indexIsNode ? QVariant() : item->curves.at(index.row())->visible(); 0288 0289 case CurveIsIsolatedRole: { 0290 const bool isVisible = item->curves.at(index.row())->visible(); 0291 if (!isVisible) 0292 return false; 0293 0294 int numVisible = 0; 0295 for (int i = 0; i < item->curves.size(); i++) { 0296 if ( numVisible > 1) 0297 return false; 0298 0299 if (item->curves.at(i)->visible()) 0300 numVisible++; 0301 } 0302 0303 return (numVisible == 1); 0304 } 0305 case NodeColorRole: { 0306 0307 if (!indexIsNode) 0308 return QVariant(); 0309 0310 KisNodeViewColorScheme nodeColorScheme; 0311 const QColor backgroundColor = qApp->palette().color(QPalette::Button); 0312 const int colorLabelIndex = item->dummy->node()->colorLabelIndex(); 0313 const QColor nodeColor = nodeColorScheme.colorFromLabelIndex(colorLabelIndex); 0314 return colorLabelIndex > 0 ? KisPaintingTweaks::blendColors(nodeColor, backgroundColor, 0.3) : backgroundColor; 0315 } 0316 default: 0317 break; 0318 } 0319 0320 return QVariant(); 0321 } 0322 0323 bool KisAnimCurvesChannelsModel::setData(const QModelIndex &index, const QVariant &value, int role) 0324 { 0325 quintptr parentRow = index.internalId(); 0326 bool indexIsNode = (parentRow == ID_NODE); 0327 NodeListItem *item = m_d->itemForRow(indexIsNode ? index.row() : parentRow); 0328 0329 switch (role) { 0330 case CurveVisibilityRole: 0331 KIS_ASSERT_RECOVER_BREAK(!indexIsNode); 0332 m_d->curvesModel->setCurveVisible(item->curves.at(index.row()), value.toBool()); 0333 this->dataChanged(index, index); 0334 return true; 0335 } 0336 0337 return false; 0338 } 0339 0340 0341 void KisAnimCurvesChannelsModel::clear() 0342 { 0343 qDeleteAll(m_d->items); 0344 m_d->items.clear(); 0345 }