File indexing completed on 2024-06-16 04:16:03
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 "KisAnimCurvesChannelDelegate.h" 0008 #include "KisAnimCurvesChannelsModel.h" 0009 #include "krita_utils.h" 0010 #include "kis_icon_utils.h" 0011 0012 #include <QApplication> 0013 #include <QMouseEvent> 0014 #include <QPainter> 0015 #include <QFontMetrics> 0016 0017 const int CHANNEL_LEGEND_RADIUS = 6; 0018 const int CHANNEL_ICON_SIZE = 16; 0019 0020 KisAnimCurvesChannelDelegate::KisAnimCurvesChannelDelegate(QObject *parent) 0021 : QStyledItemDelegate(parent) 0022 {} 0023 0024 QSize KisAnimCurvesChannelDelegate::sizeHint(const QStyleOptionViewItem &styleOption, const QModelIndex &index) const 0025 { 0026 const bool isCurve = index.data(KisAnimCurvesChannelsModel::CurveRole).toBool(); 0027 if (isCurve) { 0028 return QStyledItemDelegate::sizeHint(styleOption, index); 0029 } else { 0030 return QSize(24, 24); 0031 } 0032 } 0033 0034 bool KisAnimCurvesChannelDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) 0035 { 0036 if (event->type() == QEvent::MouseButtonPress) { 0037 QMouseEvent *me = static_cast<QMouseEvent*>(event); 0038 0039 if (me->button() == Qt::LeftButton) { 0040 const bool isCurve = index.data(KisAnimCurvesChannelsModel::CurveRole).toBool(); 0041 if (isCurve) { 0042 const QRect visibilityIcon = option.rect.adjusted(option.rect.width() - CHANNEL_ICON_SIZE, 0, 0, 0); 0043 0044 if (visibilityIcon.contains(me->pos())) { 0045 if (me->modifiers() & Qt::ShiftModifier) { 0046 bool currentlyIsolated = index.data(KisAnimCurvesChannelsModel::CurveIsIsolatedRole).toBool(); 0047 if (currentlyIsolated) { 0048 showAllChannels(model, index.parent()); 0049 } else { 0050 soloChannelVisibility(model, index); 0051 } 0052 } else { 0053 bool visible = index.data(KisAnimCurvesChannelsModel::CurveVisibilityRole).toBool(); 0054 model->setData(index, !visible, KisAnimCurvesChannelsModel::CurveVisibilityRole); 0055 } 0056 0057 return true; 0058 } 0059 } 0060 } 0061 } 0062 0063 return false; 0064 } 0065 0066 void KisAnimCurvesChannelDelegate::paint(QPainter *painter, const QStyleOptionViewItem &styleOption, const QModelIndex &index) const 0067 { 0068 painter->save(); 0069 0070 const bool isNode = !index.data(KisAnimCurvesChannelsModel::CurveRole).toBool(); 0071 QPalette palette = QApplication::palette(); 0072 0073 // Draw background 0074 if (isNode) { 0075 QVariant colorData = index.data(KisAnimCurvesChannelsModel::NodeColorRole); 0076 KIS_ASSERT(colorData.isValid()); 0077 0078 QColor nodeBGColor = colorData.value<QColor>(); 0079 paintNodeBackground(styleOption, painter, nodeBGColor); 0080 } else { 0081 styleOption.widget->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, 0082 &styleOption, painter, 0083 styleOption.widget); 0084 } 0085 0086 // Draw layer name.. 0087 QString text = index.data().toString(); 0088 const int iconSpace = isNode ? 0 : CHANNEL_ICON_SIZE; 0089 QRect textArea = styleOption.rect.adjusted(CHANNEL_LEGEND_RADIUS + 4, 0, -iconSpace, 0); 0090 text = styleOption.fontMetrics.elidedText(text, styleOption.textElideMode, textArea.width()); 0091 painter->setBrush(palette.buttonText()); 0092 styleOption.widget->style()->drawItemText(painter, textArea, Qt::AlignLeft | Qt::AlignVCenter, styleOption.palette, true, text, QPalette::ButtonText); 0093 0094 if (isNode) { 0095 // Draw Open / Close Arrow 0096 QRect arrow = QRect(styleOption.widget->rect().topLeft(), styleOption.rect.bottomLeft()); 0097 painter->setPen(Qt::NoPen); 0098 QStyleOptionViewItem item = styleOption; 0099 item.rect = arrow; 0100 styleOption.widget->style()->drawPrimitive(QStyle::PE_IndicatorBranch, 0101 &item, painter, 0102 styleOption.widget); 0103 } else { 0104 QVariant colorData = index.data(KisAnimCurvesChannelsModel::CurveColorRole); 0105 QColor color = colorData.value<QColor>(); 0106 0107 QPen newPen = QPen(color, CHANNEL_LEGEND_RADIUS); 0108 newPen.setCapStyle(Qt::RoundCap); 0109 painter->setPen(newPen); 0110 0111 if (index.data(KisAnimCurvesChannelsModel::CurveVisibilityRole).toBool()) { 0112 painter->setBrush(color); 0113 } else { 0114 painter->setBrush(QBrush()); 0115 } 0116 0117 const int y = styleOption.rect.top() + styleOption.rect.height() / 2; 0118 const QPoint left = QPoint(styleOption.rect.left() - CHANNEL_LEGEND_RADIUS, y); 0119 const QPoint right = QPoint(styleOption.rect.left(), y); 0120 painter->drawLine(left, right); 0121 } 0122 0123 // Draw buttons.. 0124 if (!isNode) { 0125 QRect iconArea = styleOption.rect.adjusted(styleOption.rect.width() - iconSpace, 0, 0, 0); 0126 const bool isVisible = index.data(KisAnimCurvesChannelsModel::CurveVisibilityRole).toBool(); 0127 QIcon visibilityIcon = isVisible ? KisIconUtils::loadIcon("visible") : KisIconUtils::loadIcon("novisible"); 0128 visibilityIcon.paint(painter, iconArea); 0129 } 0130 0131 painter->restore(); 0132 } 0133 0134 void KisAnimCurvesChannelDelegate::paintNodeBackground(const QStyleOptionViewItem &styleOption, QPainter *painter, const QColor &nodeColor) const 0135 { 0136 const bool hasValidStyle = styleOption.widget ? styleOption.widget->isEnabled() : (styleOption.state & QStyle::State_Enabled); 0137 QPalette::ColorGroup cg = hasValidStyle ? QPalette::Normal : QPalette::Disabled; 0138 0139 QRect viewArea = styleOption.rect; 0140 const QWidget* const widget = styleOption.widget; 0141 KIS_ASSERT(widget); 0142 viewArea.setLeft(widget->rect().left()); 0143 0144 { // Highlight, Shadow and Selection Color 0145 const QColor highlight = nodeColor.lighter(115); 0146 const QColor shadow = nodeColor.darker(105); 0147 painter->fillRect(viewArea, highlight); 0148 painter->fillRect(viewArea.adjusted(0,6,0,0), shadow); 0149 0150 if ( (styleOption.state & QStyle::State_Selected) 0151 && widget->style()->proxy()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected, &styleOption, widget)) { 0152 painter->fillRect(viewArea, styleOption.palette.brush(cg, QPalette::Highlight)); 0153 } 0154 } 0155 0156 { // Center "Neutral" Band 0157 viewArea -= QMargins(0, 2, 0, 2); 0158 painter->fillRect(viewArea, nodeColor); 0159 } 0160 } 0161 0162 void KisAnimCurvesChannelDelegate::soloChannelVisibility(QAbstractItemModel *model, const QModelIndex &channelIndex) 0163 { 0164 KIS_SAFE_ASSERT_RECOVER_RETURN(channelIndex.parent().isValid()); //We need to have a parent "node" to isolate. 0165 0166 const int numCurves = model->rowCount(channelIndex.parent()); 0167 const int clickedCurve = channelIndex.row(); 0168 const QModelIndex& nodeIndex = channelIndex.parent(); 0169 0170 for (int i = 0; i < numCurves; i++) { 0171 if (i == clickedCurve) { 0172 model->setData(channelIndex, true, KisAnimCurvesChannelsModel::CurveVisibilityRole); 0173 } else { 0174 QModelIndex indexToToggle = model->index(i, channelIndex.column(), nodeIndex); 0175 model->setData(indexToToggle, false, KisAnimCurvesChannelsModel::CurveVisibilityRole); 0176 } 0177 } 0178 } 0179 0180 void KisAnimCurvesChannelDelegate::showAllChannels(QAbstractItemModel *model, const QModelIndex &nodeIndex ) 0181 { 0182 KIS_SAFE_ASSERT_RECOVER_RETURN(nodeIndex.isValid() && !nodeIndex.parent().isValid()); //We should have no parent node here. 0183 0184 const int numCurves = model->rowCount(nodeIndex); 0185 0186 for (int i = 0; i < numCurves; i++) { 0187 QModelIndex curveIndex = model->index(i, 0, nodeIndex); 0188 model->setData(curveIndex, true, KisAnimCurvesChannelsModel::CurveVisibilityRole); 0189 } 0190 }