Krita Source Code Documentation
Loading...
Searching...
No Matches
KisAnimCurvesChannelDelegate.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2016 Jouni Pentikäinen <joupent@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
9#include "krita_utils.h"
10#include "kis_icon_utils.h"
11
12#include <QApplication>
13#include <QMouseEvent>
14#include <QPainter>
15
17const int CHANNEL_ICON_SIZE = 16;
18
20 : QStyledItemDelegate(parent)
21{}
22
23QSize KisAnimCurvesChannelDelegate::sizeHint(const QStyleOptionViewItem &styleOption, const QModelIndex &index) const
24{
25 const bool isCurve = index.data(KisAnimCurvesChannelsModel::CurveRole).toBool();
26 if (isCurve) {
27 return QStyledItemDelegate::sizeHint(styleOption, index);
28 } else {
29 return QSize(24, 24);
30 }
31}
32
33bool KisAnimCurvesChannelDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
34{
35 if (event->type() == QEvent::MouseButtonPress) {
36 QMouseEvent *me = static_cast<QMouseEvent*>(event);
37
38 if (me->button() == Qt::LeftButton) {
39 const bool isCurve = index.data(KisAnimCurvesChannelsModel::CurveRole).toBool();
40 if (isCurve) {
41 const QRect visibilityIcon = option.rect.adjusted(option.rect.width() - CHANNEL_ICON_SIZE, 0, 0, 0);
42
43 if (visibilityIcon.contains(me->pos())) {
44 if (me->modifiers() & Qt::ShiftModifier) {
45 bool currentlyIsolated = index.data(KisAnimCurvesChannelsModel::CurveIsIsolatedRole).toBool();
46 if (currentlyIsolated) {
47 showAllChannels(model, index.parent());
48 } else {
49 soloChannelVisibility(model, index);
50 }
51 } else {
52 bool visible = index.data(KisAnimCurvesChannelsModel::CurveVisibilityRole).toBool();
53 model->setData(index, !visible, KisAnimCurvesChannelsModel::CurveVisibilityRole);
54 }
55
56 return true;
57 }
58 }
59 }
60 }
61
62 return false;
63}
64
65void KisAnimCurvesChannelDelegate::paint(QPainter *painter, const QStyleOptionViewItem &styleOption, const QModelIndex &index) const
66{
67 painter->save();
68
69 const bool isNode = !index.data(KisAnimCurvesChannelsModel::CurveRole).toBool();
70 QPalette palette = QApplication::palette();
71
72 // Draw background
73 if (isNode) {
74 QVariant colorData = index.data(KisAnimCurvesChannelsModel::NodeColorRole);
75 KIS_ASSERT(colorData.isValid());
76
77 QColor nodeBGColor = colorData.value<QColor>();
78 paintNodeBackground(styleOption, painter, nodeBGColor);
79 } else {
80 styleOption.widget->style()->drawPrimitive(QStyle::PE_PanelItemViewItem,
81 &styleOption, painter,
82 styleOption.widget);
83 }
84
85 // Draw layer name..
86 QString text = index.data().toString();
87 const int iconSpace = isNode ? 0 : CHANNEL_ICON_SIZE;
88 QRect textArea = styleOption.rect.adjusted(CHANNEL_LEGEND_RADIUS + 4, 0, -iconSpace, 0);
89 text = styleOption.fontMetrics.elidedText(text, styleOption.textElideMode, textArea.width());
90 painter->setBrush(palette.buttonText());
91 styleOption.widget->style()->drawItemText(painter, textArea, Qt::AlignLeft | Qt::AlignVCenter, styleOption.palette, true, text, QPalette::ButtonText);
92
93 if (isNode) {
94 // Draw Open / Close Arrow
95 QRect arrow = QRect(styleOption.widget->rect().topLeft(), styleOption.rect.bottomLeft());
96 painter->setPen(Qt::NoPen);
97 QStyleOptionViewItem item = styleOption;
98 item.rect = arrow;
99 styleOption.widget->style()->drawPrimitive(QStyle::PE_IndicatorBranch,
100 &item, painter,
101 styleOption.widget);
102 } else {
103 QVariant colorData = index.data(KisAnimCurvesChannelsModel::CurveColorRole);
104 QColor color = colorData.value<QColor>();
105
106 QPen newPen = QPen(color, CHANNEL_LEGEND_RADIUS);
107 newPen.setCapStyle(Qt::RoundCap);
108 painter->setPen(newPen);
109
110 if (index.data(KisAnimCurvesChannelsModel::CurveVisibilityRole).toBool()) {
111 painter->setBrush(color);
112 } else {
113 painter->setBrush(QBrush());
114 }
115
116 const int y = styleOption.rect.top() + styleOption.rect.height() / 2;
117 const QPoint left = QPoint(styleOption.rect.left() - CHANNEL_LEGEND_RADIUS, y);
118 const QPoint right = QPoint(styleOption.rect.left(), y);
119 painter->drawLine(left, right);
120 }
121
122 // Draw buttons..
123 if (!isNode) {
124 QRect iconArea = styleOption.rect.adjusted(styleOption.rect.width() - iconSpace, 0, 0, 0);
125 const bool isVisible = index.data(KisAnimCurvesChannelsModel::CurveVisibilityRole).toBool();
126 QIcon visibilityIcon = isVisible ? KisIconUtils::loadIcon("visible") : KisIconUtils::loadIcon("novisible");
127 visibilityIcon.paint(painter, iconArea);
128 }
129
130 painter->restore();
131}
132
133void KisAnimCurvesChannelDelegate::paintNodeBackground(const QStyleOptionViewItem &styleOption, QPainter *painter, const QColor &nodeColor) const
134{
135 const bool hasValidStyle = styleOption.widget ? styleOption.widget->isEnabled() : (styleOption.state & QStyle::State_Enabled);
136 QPalette::ColorGroup cg = hasValidStyle ? QPalette::Normal : QPalette::Disabled;
137
138 QRect viewArea = styleOption.rect;
139 const QWidget* const widget = styleOption.widget;
140 KIS_ASSERT(widget);
141 viewArea.setLeft(widget->rect().left());
142
143 { // Highlight, Shadow and Selection Color
144 const QColor highlight = nodeColor.lighter(115);
145 const QColor shadow = nodeColor.darker(105);
146 painter->fillRect(viewArea, highlight);
147 painter->fillRect(viewArea.adjusted(0,6,0,0), shadow);
148
149 if ( (styleOption.state & QStyle::State_Selected)
150 && widget->style()->proxy()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected, &styleOption, widget)) {
151 painter->fillRect(viewArea, styleOption.palette.brush(cg, QPalette::Highlight));
152 }
153 }
154
155 { // Center "Neutral" Band
156 viewArea -= QMargins(0, 2, 0, 2);
157 painter->fillRect(viewArea, nodeColor);
158 }
159}
160
161void KisAnimCurvesChannelDelegate::soloChannelVisibility(QAbstractItemModel *model, const QModelIndex &channelIndex)
162{
163 KIS_SAFE_ASSERT_RECOVER_RETURN(channelIndex.parent().isValid()); //We need to have a parent "node" to isolate.
164
165 const int numCurves = model->rowCount(channelIndex.parent());
166 const int clickedCurve = channelIndex.row();
167 const QModelIndex& nodeIndex = channelIndex.parent();
168
169 for (int i = 0; i < numCurves; i++) {
170 if (i == clickedCurve) {
171 model->setData(channelIndex, true, KisAnimCurvesChannelsModel::CurveVisibilityRole);
172 } else {
173 QModelIndex indexToToggle = model->index(i, channelIndex.column(), nodeIndex);
174 model->setData(indexToToggle, false, KisAnimCurvesChannelsModel::CurveVisibilityRole);
175 }
176 }
177}
178
179void KisAnimCurvesChannelDelegate::showAllChannels(QAbstractItemModel *model, const QModelIndex &nodeIndex )
180{
181 KIS_SAFE_ASSERT_RECOVER_RETURN(nodeIndex.isValid() && !nodeIndex.parent().isValid()); //We should have no parent node here.
182
183 const int numCurves = model->rowCount(nodeIndex);
184
185 for (int i = 0; i < numCurves; i++) {
186 QModelIndex curveIndex = model->index(i, 0, nodeIndex);
187 model->setData(curveIndex, true, KisAnimCurvesChannelsModel::CurveVisibilityRole);
188 }
189}
const int CHANNEL_LEGEND_RADIUS
const int CHANNEL_ICON_SIZE
void showAllChannels(QAbstractItemModel *model, const QModelIndex &nodeIndex)
bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
QSize sizeHint(const QStyleOptionViewItem &styleOption, const QModelIndex &index) const override
void paintNodeBackground(const QStyleOptionViewItem &option, QPainter *painter, const QColor &nodeColor) const
void soloChannelVisibility(QAbstractItemModel *model, const QModelIndex &index)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
#define KIS_ASSERT(cond)
Definition kis_assert.h:33
QIcon loadIcon(const QString &name)
rgba palette[MAX_PALETTE]
Definition palette.c:35