Krita Source Code Documentation
Loading...
Searching...
No Matches
KisAnimTimelineFrameDelegate.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2015 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9#include <QPen>
10#include <QPainter>
11#include <QApplication>
12#include <QSvgRenderer>
13#include <kis_painting_tweaks.h>
16
18
20 : QItemDelegate(parent),
21 stripes(64, 64)
22{
25
26 // Clone frame stripes SVG -> Pixmap..
27 QImage stripesImage(":diagonal-stripe.svg", "svg");
28 stripesImage.save("/tmp/krita_stripes.svg", "svg");
29 stripes = QPixmap::fromImage(stripesImage);
30}
31
35
36void KisAnimTimelineFrameDelegate::paintActiveFrameSelector(QPainter *painter, const QRect &rc, bool isCurrentFrame)
37{
38 painter->save();
39
40 QColor lineColor = KisAnimTimelineColors::instance()->selectorColor();
41 const int lineWidth = rc.width() > 20 ? 4 : 2;
42
43 const int x0 = rc.x();
44 const int y0 = rc.y();
45 const int x1 = rc.right();
46 const int y1 = rc.bottom();
47
48 QVector<QLine> linesDark;
49 linesDark << QLine(x0 + lineWidth / 2, y0, x0 + lineWidth / 2, y1);
50 linesDark << QLine(x1 - lineWidth / 2 + 1, y0, x1 - lineWidth / 2 + 1, y1);
51
52 QPen oldPen = painter->pen();
53 painter->setPen(QPen(lineColor, lineWidth));
54 painter->drawLines(linesDark);
55 painter->setPen(oldPen);
56
57 if (isCurrentFrame) {
58 QPen oldPen = painter->pen();
59 QBrush oldBrush(painter->brush());
60
61 painter->setPen(QPen(lineColor, 0));
62 painter->setBrush(lineColor);
63
64 painter->drawEllipse(rc.center(), 2,2);
65
66 painter->setBrush(oldBrush);
67 painter->setPen(oldPen);
68 }
69
70 painter->restore();
71}
72
73void KisAnimTimelineFrameDelegate::paintSpecialKeyframeIndicator(QPainter *painter, const QModelIndex &index, const QRect &rc) const
74{
75 painter->save();
76
77 bool doesFrameExist = index.data(KisAnimTimelineFramesModel::FrameExistsRole).toBool();
78 bool isEditable = index.data(KisAnimTimelineFramesModel::FrameEditableRole).toBool();
79 bool hasContent = index.data(KisAnimTimelineFramesModel::FrameHasContent).toBool();
80
81 QColor color = qApp->palette().color(QPalette::Highlight);
82 QColor baseColor = qApp->palette().color(QPalette::Base);
83 QColor noLabelSetColor = qApp->palette().color(QPalette::Highlight); // if no color label is used
84
85 // use color label if it exists. coloring follows very similar logic to the drawBackground() function except this is a bit simpler
86 QVariant colorLabel = index.data(KisAnimTimelineFramesModel::FrameColorLabelIndexRole);
87 if (colorLabel.isValid()) {
88 color = labelColors.at(colorLabel.toInt());
89 } else {
90 color = noLabelSetColor;
91 }
92
93 if (!isEditable) {
94 color = KisPaintingTweaks::blendColors(baseColor, color, 0.5);
95 }
96
97 if (doesFrameExist && hasContent) {
98 color = baseColor; // special keyframe will be over filled in frame, so switch color so it is shown
99 }
100
101 QPen oldPen = painter->pen();
102 QBrush oldBrush(painter->brush());
103
104 painter->setPen(QPen(color, 0));
105 painter->setBrush(color);
106
107 QPointF center = rc.center();
108 QPointF points[4] = {
109 QPointF(center.x() + 4, center.y() ),
110 QPointF(center.x() , center.y() - 4),
111 QPointF(center.x() - 4, center.y() ),
112 QPointF(center.x() , center.y() + 4)
113 };
114 painter->drawConvexPolygon(points, 4);
115
116 painter->setBrush(oldBrush);
117 painter->setPen(oldPen);
118
119 painter->restore();
120}
121
122void KisAnimTimelineFrameDelegate::drawBackground(QPainter *painter, const QModelIndex &index, const QRect &rc) const
123{
124 painter->save();
125
127 bool hasActiveLayerRole = index.data(KisAnimTimelineFramesModel::ActiveLayerRole).toBool();
128 bool doesFrameExist = index.data(KisAnimTimelineFramesModel::FrameExistsRole).toBool();
129 bool isEditable = index.data(KisAnimTimelineFramesModel::FrameEditableRole).toBool();
130 bool hasContent = index.data(KisAnimTimelineFramesModel::FrameHasContent).toBool();
131
132 QColor color; // will get re-used for determining color
133 QColor noLabelSetColor = qApp->palette().color(QPalette::Highlight); // if no color label is used
134 QColor highlightColor = qApp->palette().color(QPalette::Highlight);
135 QColor baseColor = qApp->palette().color(QPalette::Base);
136
137
138 // pass for filling in the active row with slightly color difference
139 if (hasActiveLayerRole) {
140 color = KisPaintingTweaks::blendColors(baseColor, highlightColor, 0.8);
141 painter->fillRect(rc, color);
142 } else {
143 color = KisPaintingTweaks::blendColors(baseColor, highlightColor, 0.95);
144 painter->fillRect(rc, color);
145 }
146
147 // assign background color for frame depending on if the frame has a color label or not
148 QVariant colorLabel = index.data(KisAnimTimelineFramesModel::FrameColorLabelIndexRole);
149 if (colorLabel.isValid()) {
150 color = labelColors.at(colorLabel.toInt());
151 } else {
152 color = noLabelSetColor;
153 }
154
155
156 // if layer is hidden, make the entire color more subtle.
157 // this should be in effect for both fill color and empty outline color
158 if (!isEditable) {
159 color = KisPaintingTweaks::blendColors(baseColor, color, 0.7);
160 }
161
162
163 // how do we fill in a frame that has content
164 // a keyframe will be totally filled in. A hold frame will have a line running through it
165 if (hasContent && doesFrameExist) {
166 painter->fillRect(rc, color);
167 }
168
169 // pass of outline for empty keyframes
170 if (doesFrameExist && !hasContent) {
171
172 QPen oldPen = painter->pen();
173 QBrush oldBrush(painter->brush());
174
175 painter->setPen(QPen(color, 2));
176 painter->setBrush(Qt::NoBrush);
177 painter->drawRect(rc);
178
179 painter->setBrush(oldBrush);
180 painter->setPen(oldPen);
181 }
182
183 // pass of hold frame line
184 if (!doesFrameExist && hasContent) {
185
186 // pretty much the same check as "isValid" above, but that isn't working with hold frames
187 if (colorLabel.toInt() == 0) {
188 color = noLabelSetColor;
189
190 if (!isEditable) {
191 color = KisPaintingTweaks::blendColors(baseColor, color, 0.7);
192 }
193 }
194
195
196 QPoint lineStart(rc.x(), (rc.y() + rc.height()/2));
197 QPoint lineEnd(rc.x() + rc.width(), (rc.y() + rc.height()/2));
198
199 QPen holdFramePen(color);
200 holdFramePen.setWidth(1);
201
202 painter->setPen(holdFramePen);
203 painter->drawLine(QLine(lineStart, lineEnd));
204 }
205
206 painter->restore();
207}
208
210 const QStyleOptionViewItem &option,
211 const QRect &rect) const
212{
213 // copied from Qt 4.8!
214 if ((option.state & QStyle::State_HasFocus) == 0 || !rect.isValid())
215 return;
216
217 painter->save();
218
219
220 QStyleOptionFocusRect o;
221 o.QStyleOption::operator=(option);
222 o.rect = rect;
223 o.state |= QStyle::State_KeyboardFocusChange;
224 o.state |= QStyle::State_Item;
225 QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled)
226 ? QPalette::Normal : QPalette::Disabled;
227 o.backgroundColor = option.palette.color(cg, (option.state & QStyle::State_Selected)
228 ? QPalette::Highlight : QPalette::Window);
229 const QWidget *widget = qobject_cast<QWidget*>(parent());
230 QStyle *style = widget ? widget->style() : QApplication::style();
231 style->drawPrimitive(QStyle::PE_FrameFocusRect, &o, painter, widget);
232
233 painter->restore();
234}
235
236void KisAnimTimelineFrameDelegate::drawCloneGraphics(QPainter *painter, const QRect &rect) const
237{
238 painter->save();
239
240 QBrush brush(stripes);
241 brush.setStyle(Qt::TexturePattern);
242
243 painter->setPen(Qt::NoPen);
244 painter->setBrush(brush);
245 painter->setOpacity(0.25f);
246 painter->drawRect(rect);
247
248 painter->restore();
249}
250
252 const QStyleOptionViewItem &option,
253 const QModelIndex &index) const
254{
255 // draws background as well as fills normal keyframes
256 drawBackground(painter, index, option.rect);
257
258 // Clone graphics..
260 drawCloneGraphics(painter, option.rect);
261 }
262
263 // creates a semi transparent orange rectangle in the frame that is actively selected on the active row
264 if (option.showDecorationSelected &&
265 (option.state & QStyle::State_Selected)) {
266 painter->save();
267
268 const QVariant data = index.data(KisAnimTimelineFramesModel::FrameEditableRole);
269 bool isEditable = data.isValid() ? data.toBool() : true;
270
271 QColor highlightColor = KisAnimTimelineColors::instance()->selectionColor();
272 highlightColor.setAlpha(isEditable ? 128 : 64);
273 QBrush brush = highlightColor;
274 painter->fillRect(option.rect, brush);
275
276 painter->restore();
277 }
278
279 // not sure what this is drawing
280 drawFocus(painter, option, option.rect);
281
282 // opacity keyframe, but NOT normal keyframes
283 bool specialKeys = index.data(KisAnimTimelineFramesModel::SpecialKeyframeExists).toBool();
284 if (specialKeys) {
285 paintSpecialKeyframeIndicator(painter, index, option.rect);
286 }
287
288 // creates a border and dot on the selected frame on the active row
289 bool active = index.data(KisAnimTimelineFramesModel::ActiveFrameRole).toBool();
290 bool layerIsCurrent = index.data(KisAnimTimelineFramesModel::ActiveLayerRole).toBool();
291 if (active) {
292 paintActiveFrameSelector(painter, option.rect, layerIsCurrent);
293 }
294
295 { // Shade over anything that's outside of the animation range...
296 if (index.data(KisAnimTimelineFramesModel::WithinClipRange).toBool() == false) {
297 painter->save();
298
299 painter->setOpacity(0.50f);
300 painter->fillRect(option.rect, qApp->palette().color(QPalette::Base).darker(110));
301
302 painter->restore();
303 }
304 }
305}
static KisAnimTimelineColors * instance()
void paintSpecialKeyframeIndicator(QPainter *painter, const QModelIndex &index, const QRect &rc) const
the opacity keyframe
void drawFocus(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect) const override
static void paintActiveFrameSelector(QPainter *painter, const QRect &rc, bool isCurrentFrame)
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
void drawCloneGraphics(QPainter *painter, const QRect &rect) const
void drawBackground(QPainter *painter, const QModelIndex &index, const QRect &rc) const
QVector< QColor > allColorLabels() const
QColor blendColors(const QColor &c1, const QColor &c2, qreal r1)