Krita Source Code Documentation
Loading...
Searching...
No Matches
KisAnimTimelineLayersHeader.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2015 Dmitry Kazakov <dimula73@gmail.com>
3 * SPDX-FileCopyrightText: 2020 Emmet O 'Neill <emmetoneill.pdx@gmail.com>
4 * SPDX-FileCopyrightText: 2020 Eoin O 'Neill <eoinoneill1991@gmail.com>
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
10
11#include "kis_debug.h"
12#include "kis_icon_utils.h"
13#include "kis_global.h"
14
15#include <QPainter>
16#include <QHelpEvent>
17#include <QToolTip>
18
21
22
24{
26
28
29 int numIcons(int logicalIndex) const;
30 int iconSectionWidth(int layerIndex) const;
31 QPoint getSectionLocalPosition(int layerIndex, QPoint widgetPosition) const;
32 QRect getSectionRect(int layerIndex) const;
33 QRect propertyIconRect(int logicalIndex, int iconIndex) const;
34 int propertyIconAt(int logicalIndex, const QPoint &pt);
35
37};
38
39
41 : QHeaderView(Qt::Vertical, parent),
42 m_d(new Private(this))
43{
44}
45
49
50void KisAnimTimelineLayersHeader::paintSection(QPainter *painter, const QRect &areaRect, int layerIndex) const
51{
52 QRect remainingArea = areaRect;
53
54 { // Paint background..
55 QColor bgFillColor = palette().color(QPalette::Base);
56
57 QVariant variant = model()->headerData(layerIndex, orientation(), Qt::BackgroundRole);
58 if (variant.canConvert<QBrush>()) {
59 QBrush brush = qvariant_cast<QBrush>(variant);
60 painter->setBrush(brush);
61 painter->setPen(Qt::NoPen);
62 painter->drawRect(areaRect);
63
64 bgFillColor = brush.color();
65 }
66
67 QColor rimlight = bgFillColor.lighter(115);
68 painter->setPen(QPen(rimlight, 2));
69 painter->setBrush(rimlight);
70 painter->drawLine(areaRect.topLeft(), areaRect.topRight());
71 }
72
73 // Paint active highlight..
74 const bool isLayerActive = model()->headerData(layerIndex, orientation(), KisAnimTimelineFramesModel::ActiveLayerRole).toBool();
75
76 if (isLayerActive) {
78 const int lineWidth = 2;
79
80 painter->setPen(QPen(lineColor, lineWidth));
81 painter->setBrush(lineColor);
82
83 QVector<QLine> lines;
84 lines << QLine(areaRect.topLeft(), areaRect.topRight()).translated(0,1);
85 lines << QLine(areaRect.bottomLeft(), areaRect.bottomRight()).translated(0,-1);
86 painter->drawLines(lines);
87 }
88
89 // Paint pushpin icon..
90 painter->save();
91 const bool isPinned = model()->headerData(layerIndex, orientation(), KisAnimTimelineFramesModel::PinnedToTimelineRole).toBool();
92 const uint pinWidth = areaRect.height() - 4;
93 QRect pinArea = kisTrimLeft(pinWidth, remainingArea);
94 const uint difference = pinArea.height() - pinWidth;
95 pinArea.setHeight(pinWidth); // Square to width.
96 pinArea.translate(0, difference / 2); // Center.
97
98 QIcon icon = KisIconUtils::loadIcon("krita_tool_reference_images");
99 QRect iconRect = pinArea - QMargins(5,5,5,5);
100
101 if (!isPinned) {
102 iconRect = pinArea - QMargins(6,4,4,6);
103 painter->setOpacity(0.35);
104 }
105
106 icon.paint(painter, iconRect);
107 painter->restore();
108
109 // Paint layer name..
110 const int textSpace = remainingArea.width() - m_d->iconSectionWidth(layerIndex);
111 const QRect textArea = kisTrimLeft(textSpace, remainingArea);
112 QString text = model()->headerData(layerIndex, orientation(), Qt::DisplayRole).toString();
113 text = fontMetrics().elidedText(text, textElideMode(), textArea.width());
114 style()->drawItemText(painter, textArea, Qt::AlignLeft | Qt::AlignVCenter, palette(), isEnabled(), text, QPalette::ButtonText);
115
116 // Paint property (hidden, alpha inherit, etc.) icons..
117 QVariant value = model()->headerData(layerIndex, orientation(), KisAnimTimelineFramesModel::TimelinePropertiesRole);
119
120 const int numIcons = m_d->numIcons(layerIndex);
121 for (int i = 0; i < numIcons; i++) {
122 KisAnimTimelineFramesModel::Property *prop = m_d->getPropertyAt(props, i);
123
124 const bool isActive = prop->state.toBool();
125 QIcon icon = isActive ? prop->onIcon : prop->offIcon;
126 if (!isActive) {
127 painter->setOpacity(0.35);
128 }
129 QRect iconRect = m_d->propertyIconRect(layerIndex, i).translated(areaRect.topLeft());
130 icon.paint(painter, iconRect);
131 painter->setOpacity(1.0);
132 }
133}
134
137{
138 int logical = 0;
139 for (int i = 0; i < props.size(); i++) {
140 if (props[i].isMutable) {
141 if (logical == index) {
142 return &props[i];
143 }
144
145 logical++;
146 }
147 }
148
149 return 0;
150}
151
153{
154 int result = 0;
155
156 QVariant value = q->model()->headerData(logicalIndex, q->orientation(), KisAnimTimelineFramesModel::TimelinePropertiesRole);
157 if (value.isValid()) {
159
160 Q_FOREACH (const KisAnimTimelineFramesModel::Property &p, props) {
161 if (p.isMutable) {
162 result++;
163 }
164 }
165 }
166
167 return result;
168}
169
171{
172 const int iconSize = 16;
173 const int iconPadding = 2;
174 return (iconSize + iconPadding) * numIcons(layerIndex);
175}
176
177QPoint KisAnimTimelineLayersHeader::Private::getSectionLocalPosition(int layerIndex, QPoint widgetPosition) const
178{
179 QPoint sectionTopLeft(0, q->sectionViewportPosition(layerIndex));
180 return widgetPosition - sectionTopLeft;
181}
182
184{
185 QSize baseSize = QHeaderView::sectionSizeFromContents(layerIndex);
186 const int pinSpace = baseSize.height() - 4;
187 const int padding = 8;
188
189 baseSize.setWidth(baseSize.width() + pinSpace
190 + m_d->iconSectionWidth(layerIndex) + padding);
191 return baseSize;
192}
193
195{
196 QSize sectionSize(q->viewport()->width(), q->sectionSize(layerIndex));
197 QPoint sectionTopLeft(0, q->sectionViewportPosition(layerIndex));
198 return QRect(sectionTopLeft, sectionSize);
199}
200
201QRect KisAnimTimelineLayersHeader::Private::propertyIconRect(int logicalIndex, int iconIndex) const
202{
203 QSize sectionSize(q->viewport()->width(), q->sectionSize(logicalIndex));
204
205 const int iconWidth = 16;
206 const int iconHeight = 16;
207
208 const int y = (sectionSize.height() - iconHeight) / 2;
209 const int x = sectionSize.width() -
210 (numIcons(logicalIndex) - iconIndex) * (iconWidth + 2);
211
212 return QRect(x, y, iconWidth, iconHeight);
213}
214
215int KisAnimTimelineLayersHeader::Private::propertyIconAt(int logicalIndex, const QPoint &pt)
216{
217 QPoint localPos = getSectionLocalPosition(logicalIndex, pt);
218
219 for (int i = 0; i < numIcons(logicalIndex); i++) {
220 QRect rc = propertyIconRect(logicalIndex, i);
221
222 if (rc.contains(localPos)) {
223 return i;
224 }
225 }
226
227 return -1;
228}
229
231{
232 switch (event->type()) {
233 case QEvent::ToolTip: {
237 QHelpEvent *he = static_cast<QHelpEvent*>(event);
238 int logical = logicalIndexAt(he->pos());
239 if (logical != -1) {
240
241 const int iconIndex = m_d->propertyIconAt(logical, he->pos());
242 if (iconIndex != -1) {
243
244 QVariant value = model()->headerData(logical, orientation(), KisAnimTimelineFramesModel::TimelinePropertiesRole);
246
248 m_d->getPropertyAt(props, iconIndex);
249
250 QString text = QString("%1 (%2)")
251 .arg(p->name)
252 .arg(p->state.toBool() ? i18n("on") : i18n("off"));
253
254 QToolTip::showText(he->globalPos(), text, this);
255 return true;
256 }
257 }
258 break; }
259 default:
260 break;
261 }
262
263 return QHeaderView::viewportEvent(event);
264}
265
267{
268 int layerIndex = logicalIndexAt(e->pos());
269 if (layerIndex != -1) {
270 // Handle pin click..
271 QRect layerHeaderRect = m_d->getSectionRect(layerIndex);
272 const uint pinWidth = layerHeaderRect.height() - 4;
273 QRect pinArea = kisTrimLeft(pinWidth, layerHeaderRect);
274 if (pinArea.contains(e->pos())) {
275 const bool isPinned = model()->headerData(layerIndex, orientation(), KisAnimTimelineFramesModel::PinnedToTimelineRole).toBool();
276 model()->setHeaderData(layerIndex, orientation(), !isPinned, KisAnimTimelineFramesModel::PinnedToTimelineRole);
277 return;
278 }
279
280 // Handle property click..
281 const int propertyIconIndex = m_d->propertyIconAt(layerIndex, e->pos());
282 if (propertyIconIndex != -1) {
283 QVariant value = model()->headerData(layerIndex, orientation(), KisAnimTimelineFramesModel::TimelinePropertiesRole);
285
287 m_d->getPropertyAt(props, propertyIconIndex);
288
289 bool currentState = p->state.toBool();
290 p->state = !currentState;
291
292 value.setValue(props);
293
294 model()->setHeaderData(layerIndex, orientation(), value, KisAnimTimelineFramesModel::TimelinePropertiesRole);
295 return;
296
297 } else if (e->button() == Qt::RightButton) {
298 model()->setHeaderData(layerIndex, orientation(), true, KisAnimTimelineFramesModel::ActiveLayerRole);
299 Q_EMIT sigRequestContextMenu(e->globalPos());
300 return;
301 } else if (e->button() == Qt::LeftButton) {
302 model()->setHeaderData(layerIndex, orientation(), true, KisAnimTimelineFramesModel::ActiveLayerRole);
303 }
304 }
305
306 QHeaderView::mousePressEvent(e);
307}
float value(const T *src, size_t ch)
const Params2D p
unsigned int uint
int iconSize(qreal width, qreal height)
static KisAnimTimelineColors * instance()
void paintSection(QPainter *painter, const QRect &rect, int layerIndex) const override
QSize sectionSizeFromContents(int layerIndex) const override
bool viewportEvent(QEvent *event) override
const QScopedPointer< Private > m_d
void mousePressEvent(QMouseEvent *event) override
void sigRequestContextMenu(const QPoint &pos)
QRectF kisTrimLeft(int width, QRectF &toTakeFrom)
Definition kis_global.h:288
QIcon loadIcon(const QString &name)
rgba palette[MAX_PALETTE]
Definition palette.c:35
QPoint getSectionLocalPosition(int layerIndex, QPoint widgetPosition) const
int propertyIconAt(int logicalIndex, const QPoint &pt)
KisAnimTimelineFramesModel::Property * getPropertyAt(KisAnimTimelineFramesModel::PropertyList &props, int index)
QRect propertyIconRect(int logicalIndex, int iconIndex) const