Krita Source Code Documentation
Loading...
Searching...
No Matches
StoryboardDelegate.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2020 Saurabh Kumar <saurabhk660@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8#include "StoryboardModel.h"
9
10#include <QLineEdit>
11#include <QTextEdit>
12#include <QDebug>
13#include <QStyle>
14#include <QPainter>
15#include <QApplication>
16#include <QSize>
17#include <QMouseEvent>
18#include <QSpinBox>
19#include <QScrollBar>
20
21#include <kis_icon.h>
25
26
28 : QStyledItemDelegate(parent)
29 , m_view(nullptr)
30 , m_imageSize(QSize())
31{
32}
33
37
38void StoryboardDelegate::paint(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
39{
40 p->save();
41 {
42 QStyle *style = option.widget ? option.widget->style() : QApplication::style();
43 style->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, p, option.widget);
44
45 p->setFont(option.font);
46 if (!index.isValid()) {
47 p->restore();
48 return;
49 }
50 if (!index.parent().isValid()) {
51 QRect parentRect = option.rect;
52 p->setPen(QPen(option.palette.window(), 2));
53 p->drawRect(parentRect);
54
55 parentRect.setTopLeft(parentRect.topLeft() + QPoint(4, 4));
56 parentRect.setBottomRight(parentRect.bottomRight() - QPoint(4, 4));
57
58 if (option.state & QStyle::State_Selected) {
59 p->fillRect(option.rect, option.palette.highlight());
60 }
61 else {
62 p->fillRect(option.rect, option.palette.window());
63 }
64 p->eraseRect(parentRect);
65 }
66 else {
67 //draw the child items
68 int childNum = index.row();
69 QString data = index.data().toString();
70
71 switch (childNum)
72 {
74 {
76 QRect frameNumRect = option.rect;
77 frameNumRect.setHeight(m_view->fontMetrics().height()+3);
78 frameNumRect.setWidth(3 * m_view->fontMetrics().horizontalAdvance("0") + 2);
79 frameNumRect.moveBottom(option.rect.top()-1);
80 p->setPen(QPen(option.palette.dark(), 2));
81 p->drawRect(frameNumRect);
82 p->setPen(QPen(option.palette.text(), 1));
83 p->drawText(frameNumRect, Qt::AlignHCenter | Qt::AlignVCenter, data);
84
85 if (!m_imageSize.isEmpty()) {
86 float scale = qMin(option.rect.height() / (float)m_imageSize.height(), (float)option.rect.width() / m_imageSize.width());
87 QRect thumbnailRect = option.rect;
88 thumbnailRect.setSize(m_imageSize * scale);
89 thumbnailRect.moveCenter(option.rect.center());
90
91 QPixmap thumbnailPixmap= index.data(Qt::UserRole).value<QPixmap>();
92 p->drawPixmap(thumbnailRect, thumbnailPixmap);
93 }
94 p->setPen(QPen(option.palette.dark(), 2));
95 p->drawRect(option.rect);
96
97 QRect buttonsRect = option.rect;
98 buttonsRect.setTop(option.rect.bottom() - 22);
99
100 buttonsRect.setWidth(22);
101 buttonsRect.moveBottomLeft(option.rect.bottomLeft());
102 QIcon addIcon = KisIconUtils::loadIcon("list-add");
103 p->fillRect(buttonsRect, option.palette.window());
104 addIcon.paint(p, buttonsRect);
105
106 buttonsRect.moveBottomRight(option.rect.bottomRight());
107 QIcon deleteIcon = KisIconUtils::loadIcon("edit-delete");
108 p->fillRect(buttonsRect, option.palette.window());
109 deleteIcon.paint(p, buttonsRect);
110 }
111 else {
112 QRect frameNumRect = option.rect;
113 p->setPen(QPen(option.palette.dark(), 2));
114 p->drawRect(frameNumRect);
115 p->setPen(QPen(option.palette.text(), 1));
116 p->drawText(frameNumRect, Qt::AlignHCenter | Qt::AlignVCenter, data);
117 }
118 break;
119 }
121 {
122 QRect itemNameRect = option.rect;
123 itemNameRect.setLeft(option.rect.left() + 5);
124 p->setPen(QPen(option.palette.text(), 1));
125 p->drawText(itemNameRect, Qt::AlignLeft | Qt::AlignVCenter, data);
126 p->setPen(QPen(option.palette.dark(), 2));
127 p->drawRect(option.rect);
128 break;
129 }
131 {
132 drawSpinBox(p, option, data, i18nc("suffix in spin box in storyboard that means 'seconds'", "s"));
133 break;
134 }
136 {
137 drawSpinBox(p, option, data, i18nc("suffix in spin box in storyboard that means 'frames'", "f"));
138 break;
139 }
140 default:
141 {
142 KIS_SAFE_ASSERT_RECOVER_RETURN(index.model());
143 const StoryboardModel* model = dynamic_cast<const StoryboardModel*>(index.model());
145 if (m_view->commentIsVisible() && model->getComment(index.row() - 4).visibility) {
146 p->setPen(QPen(option.palette.dark(), 2));
147 drawCommentHeader(p, option, index);
148 }
149 break;
150 }
151 }
152 }
153 }
154 p->restore();
155}
156
157void StoryboardDelegate::drawSpinBox(QPainter *p, const QStyleOptionViewItem &option, QString data, QString suffix) const
158{
159 QStyle *style = option.widget ? option.widget->style() : QApplication::style();
160 QStyleOptionSpinBox spinBoxOption;
161 spinBoxOption.stepEnabled = QAbstractSpinBox::StepDownEnabled | QAbstractSpinBox::StepUpEnabled;
162 spinBoxOption.subControls = QStyle::SC_SpinBoxUp | QStyle::SC_SpinBoxDown;
163 spinBoxOption.rect = option.rect;
164 p->setPen(QPen(option.palette.dark(), 2));
165 p->drawRect(option.rect);
166 style->drawComplexControl(QStyle::CC_SpinBox, &spinBoxOption, p, option.widget);
167
168 QRect rect = style->subControlRect(QStyle::CC_SpinBox, &spinBoxOption,
169 QStyle::QStyle::SC_SpinBoxEditField);
170 rect.moveTopLeft(option.rect.topLeft());
171 p->setPen(QPen(option.palette.text(), 1));
172 p->drawText(rect, Qt::AlignLeft | Qt::AlignVCenter, data + suffix);
173}
174
175QStyleOptionSlider StoryboardDelegate::drawCommentHeader(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
176{
177 QStyle *style = option.widget ? option.widget->style() : QApplication::style();
178 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(index.model(), QStyleOptionSlider());
179 const StoryboardModel* model = dynamic_cast<const StoryboardModel*>(index.model());
180 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(model, QStyleOptionSlider());
181 QString data = index.data().toString();
182
183 QRect titleRect = option.rect;
184 titleRect.setHeight(option.fontMetrics.height() + 3);
185 if (p) {
186 p->setPen(QPen(option.palette.text(), 1));
187 p->drawText(titleRect, Qt::AlignLeft | Qt::AlignVCenter, model->getComment(index.row() - 4).name);
188 p->setPen(QPen(option.palette.dark(), 2));
189 p->drawRect(titleRect);
190 }
191
192 QRect contentRect = option.rect;
193 contentRect.setTop(option.rect.top() + option.fontMetrics.height() + 3);
194 if (p) {
195 p->setPen(QPen(option.palette.dark(), 2));
196 p->drawRect(contentRect);
197 p->save();
198 }
199 contentRect.setTopLeft(contentRect.topLeft() + QPoint(5, 5));
200 contentRect.setBottomRight(contentRect.bottomRight() - QPoint(5, 5));
201
202 int scrollValue = index.data(Qt::UserRole).toInt();
203
204 //draw comment
205 QRect commentRect = contentRect;
206 commentRect.setRight(contentRect.right() - 15);
207 QTextDocument doc;
208
209 doc.setTextWidth(commentRect.width());
210 doc.setDocumentMargin(0);
211 doc.setDefaultFont(option.font);
212 QStringList lines = data.split('\n');
213 QString HTML;
214 Q_FOREACH( const QString& line, lines) {
215 HTML.append("<p>" + line + "</p>");
216 }
217 doc.setHtml(HTML);
218 QRectF clipRect = commentRect;
219 clipRect.moveTopLeft(QPoint(0, 0 + scrollValue));
220 if (p) {
221 p->translate(QPoint(commentRect.topLeft().x(), commentRect.topLeft().y() - scrollValue));
222 p->setPen(QPen(option.palette.text(), 1));
223 doc.drawContents(p, clipRect);
224 p->restore();
225 }
226 //draw scroll bar
227 QStyleOptionSlider scrollbarOption;
228 scrollbarOption.sliderPosition = scrollValue;
229 scrollbarOption.minimum = 0;
230 scrollbarOption.maximum = qMax(0.0, doc.size().height() - contentRect.height());
231 scrollbarOption.sliderPosition = qMin(scrollValue, scrollbarOption.maximum);
232 scrollbarOption.pageStep = contentRect.height() - 2;
233 scrollbarOption.orientation = Qt::Vertical;
234
235 QRect scrollRect = option.rect;
236 scrollRect.setSize(QSize(15, option.rect.height() - option.fontMetrics.height() - 3));
237 scrollRect.moveTopLeft(QPoint(0, 0));
238 scrollbarOption.rect = scrollRect;
239
240 if (p && scrollbarOption.pageStep <= doc.size().height()) {
241 p->save();
242 p->setPen(QPen(option.palette.dark(), 2));
243 p->translate(QPoint( option.rect.right()-15, option.rect.top() + option.fontMetrics.height() + 3));
244 style->drawComplexControl(QStyle::CC_ScrollBar, &scrollbarOption, p, option.widget);
245 p->restore();
246 }
247 return scrollbarOption;
248}
249
250QSize StoryboardDelegate::sizeHint(const QStyleOptionViewItem &option,
251 const QModelIndex &index) const
252{
253 if (!index.parent().isValid()) {
254 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(index.model(), option.rect.size());
255 if (m_view->itemOrientation() == Qt::Vertical) {
256 int width = option.widget->width() - 17;
257 const StoryboardModel* model = dynamic_cast<const StoryboardModel*>(index.model());
258 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(model, option.rect.size());
259 int numComments = model->visibleCommentCount();
260 int numItem = width/250;
261 if (numItem <= 0) {
262 numItem = 1;
263 }
264
265 int thumbnailheight = m_view->thumbnailIsVisible() ? 120 : 0;
266 int commentHeight = m_view->commentIsVisible() ? numComments*100 : 0;
267 return QSize(width / numItem, thumbnailheight + option.fontMetrics.height() + 3 + commentHeight + 10);
268 }
269 else {
270 const StoryboardModel* model = dynamic_cast<const StoryboardModel*>(index.model());
271 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(model, option.rect.size());
272 int numComments = model->visibleCommentCount();
273 int commentWidth = 0;
274 if (numComments && m_view->commentIsVisible()) {
275 commentWidth = qMax(200, (m_view->viewport()->width() - 250) / numComments);
276 }
277 int width = 250 + numComments * commentWidth;
278 return QSize(width + 10, 120 + option.fontMetrics.height() + 3 + 10);
279 }
280 }
281 else {
282 return option.rect.size();
283 }
284}
285
286QWidget *StoryboardDelegate::createEditor(QWidget *parent,
287 const QStyleOptionViewItem &option ,
288 const QModelIndex &index) const
289{
290 Q_UNUSED(option);
291 //only create editor for children
292 if (index.parent().isValid()) {
293 int row = index.row();
294 switch (row)
295 {
297 return nullptr;
299 {
300 QLineEdit *editor = new QLineEdit(parent);
301 return editor;
302 }
304 {
305 QSpinBox *spinbox = new QSpinBox(parent);
306 spinbox->setRange(0, 999);
307 spinbox->setSuffix(i18nc("suffix in spin box in storyboard that means 'seconds'", "s"));
308 return spinbox;
309 }
311 {
312 QSpinBox *spinbox = new QSpinBox(parent);
313 spinbox->setRange(0, 99);
314 spinbox->setSuffix(i18nc("suffix in spin box in storyboard that means 'frames'", "f"));
315 return spinbox;
316 }
317 default: //for comments
318 {
319 QTextEdit *editor = new LimitedTextEditor(280, parent);
320 return editor;
321 }
322 }
323 }
324 return nullptr;
325}
326
327bool StoryboardDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
328{
330 if ((event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick)
331 && (index.flags() & Qt::ItemIsEnabled))
332 {
333 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
334 const bool leftButton = mouseEvent->buttons() & Qt::LeftButton;
335
336 //handle the duration edit event
337 if (index.parent().isValid() && (index.row() == StoryboardItem::DurationSecond || index.row() == StoryboardItem::DurationFrame)) {
338 QRect upButton = spinBoxUpButton(option);
339 QRect downButton = spinBoxDownButton(option);
340
341 bool upButtonClicked = upButton.isValid() && upButton.contains(mouseEvent->pos());
342 bool downButtonClicked = downButton.isValid() && downButton.contains(mouseEvent->pos());
343
344 StoryboardModel* sbModel = dynamic_cast<StoryboardModel*>(model);
346 if (leftButton && upButtonClicked) {
348 index.data().toInt() + 1,
349 index.parent().row(),
350 index.row(),
351 sbModel);
352 if (sbModel->setData(index, index.data().toInt() + 1)) {
353 sbModel->pushUndoCommand(cmd);
354 }
355 return true;
356 }
357 else if (leftButton && downButtonClicked) {
359 index.data().toInt() - 1,
360 index.parent().row(),
361 index.row(),
362 sbModel);
363 if (sbModel->setData(index, index.data().toInt() - 1)) {
364 sbModel->pushUndoCommand(cmd);
365 }
366 return true;
367 }
368 }
369 else if (index.parent().isValid() && index.row() >= StoryboardItem::Comments) {
370 QStyleOptionSlider scrollBarOption = drawCommentHeader(nullptr, option, index);
371 QRect upButton = scrollUpButton(option, scrollBarOption);
372 QRect downButton = scrollDownButton(option, scrollBarOption);
373
374 bool upButtonClicked = upButton.isValid() && upButton.contains(mouseEvent->pos());
375 bool downButtonClicked = downButton.isValid() && downButton.contains(mouseEvent->pos());
376
377 if (leftButton && upButtonClicked) {
378 int lastValue = model->data(index, Qt::UserRole).toInt();
379 int value = lastValue - option.fontMetrics.height();
380 StoryboardModel* modelSB = dynamic_cast<StoryboardModel*>(model);
382 modelSB->setCommentScrollData(index, qMax(0, value));
383 return true;
384 }
385 else if (leftButton && downButtonClicked) {
386 int lastValue = model->data(index, Qt::UserRole).toInt();
387 int value = lastValue + option.fontMetrics.height();
388 StoryboardModel* modelSB = dynamic_cast<StoryboardModel*>(model);
390 modelSB->setCommentScrollData(index, qMin(scrollBarOption.maximum, value));
391 return true;
392 }
393 }
394
395 else if (index.parent().isValid() && index.row() == StoryboardItem::FrameNumber && m_view->thumbnailIsVisible()) { //thumbnail add/delete events
396 QRect addItemButton(QPoint(0, 0), QSize(22, 22));
397 addItemButton.moveBottomLeft(option.rect.bottomLeft());
398
399 QRect deleteItemButton(QPoint(0, 0), QSize(22, 22));
400 deleteItemButton.moveBottomRight(option.rect.bottomRight());
401
402 bool addItemButtonClicked = addItemButton.isValid() && addItemButton.contains(mouseEvent->pos());
403 bool deleteItemButtonClicked = deleteItemButton.isValid() && deleteItemButton.contains(mouseEvent->pos());
404
405 StoryboardModel* sbModel = dynamic_cast<StoryboardModel*>(model);
407 if (leftButton && addItemButtonClicked) {
408 sbModel->insertItem(index.parent(), true);
409 return true;
410 }
411 else if (leftButton && deleteItemButtonClicked) {
412 int row = index.parent().row();
413 KisRemoveStoryboardCommand *command = new KisRemoveStoryboardCommand(row, sbModel->getData().at(row), sbModel);
414
415 sbModel->removeItem(index.parent(), command);
416 sbModel->pushUndoCommand(command);
417 return true;
418 }
419 }
420 }
421
422 if ((event->type() == QEvent::MouseMove) && (index.flags() & Qt::ItemIsEnabled)) {
423 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
424 const bool leftButton = mouseEvent->buttons() & Qt::LeftButton;
425
426 QStyleOptionSlider scrollBarOption = drawCommentHeader(nullptr, option, index);
427 QRect scrollBarRect = scrollBar(option, scrollBarOption);
428
429 bool lastClickPosInScroll = scrollBarRect.isValid() && scrollBarRect.contains(m_lastDragPos);
430 bool currClickPosInScroll = scrollBarRect.isValid() && scrollBarRect.contains(mouseEvent->pos());
431
432 if (leftButton && index.parent().isValid() && index.row() >= StoryboardItem::Comments) {
433 if (lastClickPosInScroll && currClickPosInScroll) {
434 int lastValue = model->data(index, Qt::UserRole).toInt();
435 int value = lastValue + mouseEvent->pos().y() - m_lastDragPos.y();
436
437 StoryboardModel* modelSB = dynamic_cast<StoryboardModel*>(model);
439 if (value >= 0 && value <= scrollBarOption.maximum) {
440 modelSB->setCommentScrollData(index, value);
441 return true;
442 }
443 return false;
444 }
445 m_lastDragPos = mouseEvent->pos();
446 }
447 }
448
449 return false;
450}
451
452//set the existing data in the editor
454 const QModelIndex &index) const
455{
456 QVariant value = index.data();
457 if (index.parent().isValid()) {
458 int row = index.row();
459 switch (row)
460 {
461 case StoryboardItem::FrameNumber: //frame thumbnail is uneditable
462 return;
464 {
465 QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
466 lineEdit->setText(value.toString());
467 return;
468 }
471 {
472 QSpinBox *spinbox = static_cast<QSpinBox*>(editor);
473 spinbox->setValue(value.toInt());
474 return;
475 }
476 default: // for comments
477 {
478 QTextEdit *textEdit = static_cast<QTextEdit*>(editor);
479 textEdit->setText(value.toString());
480 textEdit->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor);
481 textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
482 textEdit->verticalScrollBar()->setProperty("index", index);
483 connect(textEdit->verticalScrollBar(), SIGNAL(sliderMoved(int)), this, SLOT(slotCommentScrolledTo(int)));
484 return;
485 }
486 }
487 }
488}
489
490void StoryboardDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
491 const QModelIndex &index) const
492{
493 KIS_ASSERT(model);
494 QVariant value = index.data();
495 if (index.parent().isValid()) {
496 int row = index.row();
497 switch (row)
498 {
499 case StoryboardItem::FrameNumber: //frame thumbnail is uneditable
500 return;
502 {
503 QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
504 QString value = lineEdit->text();
505 model->setData(index, value, Qt::EditRole);
506 return;
507 }
510 {
511 QSpinBox *spinbox = static_cast<QSpinBox*>(editor);
512 int value = spinbox->value();
513
514 StoryboardModel* sbModel = dynamic_cast<StoryboardModel*>(model);
517 value,
518 index.parent().row(),
519 index.row(),
520 sbModel);
521 if (sbModel->setData(index, value)) {
522 sbModel->pushUndoCommand(cmd);
523 }
524 return;
525 }
526 default: // for comments
527 {
528 QTextEdit *textEdit = static_cast<QTextEdit*>(editor);
529 QString value = textEdit->toPlainText();
530
531 StoryboardModel* sbModel = dynamic_cast<StoryboardModel*>(model);
534 value,
535 index.parent().row(),
536 index.row(),
537 sbModel);
538
539 if (sbModel->setData(index, value)) {
540 sbModel->pushUndoCommand(cmd);
541 }
542
543 return;
544 }
545 }
546 }
547}
548
550 const QStyleOptionViewItem &option, const QModelIndex &index) const
551{
552 if (index.row() < StoryboardItem::Comments) {
553 editor->setGeometry(option.rect);
554 }
555 else { //for comment textedits
556 QRect commentRect = option.rect;
557 commentRect.setTop(option.rect.top() + option.fontMetrics.height() + 3);
558 editor->setGeometry(commentRect);
559 }
560}
561
563{
564 m_view = view;
565}
566
567QRect StoryboardDelegate::spinBoxUpButton(const QStyleOptionViewItem &option)
568{
569 QStyle *style = option.widget ? option.widget->style() : QApplication::style();
570 QStyleOptionSpinBox spinOption;
571 spinOption.rect = option.rect;
572 QRect rect = style->subControlRect(QStyle::CC_SpinBox, &spinOption,
573 QStyle::QStyle::SC_SpinBoxUp);
574 rect.moveTopRight(option.rect.topRight());
575 return rect;
576}
577
578QRect StoryboardDelegate::spinBoxDownButton(const QStyleOptionViewItem &option)
579{
580 QStyle *style = option.widget ? option.widget->style() : QApplication::style();
581 QStyleOptionSpinBox spinOption;
582 spinOption.rect = option.rect;
583 QRect rect = style->subControlRect(QStyle::CC_SpinBox, &spinOption,
584 QStyle::QStyle::SC_SpinBoxDown);
585 rect.moveBottomRight(option.rect.bottomRight());
586 return rect;
587}
588
589QRect StoryboardDelegate::spinBoxEditField(const QStyleOptionViewItem &option)
590{
591 QStyle *style = option.widget ? option.widget->style() : QApplication::style();
592 QStyleOptionSpinBox spinOption;
593 spinOption.rect = option.rect;
594 QRect rect = style->subControlRect(QStyle::CC_SpinBox, &spinOption,
595 QStyle::QStyle::SC_SpinBoxEditField);
596 rect.moveTopLeft(option.rect.topLeft());
597 return rect;
598}
599
601{
602 const QModelIndex index = sender()->property("index").toModelIndex();
604 StoryboardModel* model = dynamic_cast<StoryboardModel*>(m_view->model());
606 model->setCommentScrollData(index, value);
607}
608
609QRect StoryboardDelegate::scrollBar(const QStyleOptionViewItem &option, QStyleOptionSlider &scrollBarOption) const
610{
611 QStyle *style = option.widget ? option.widget->style() : QApplication::style();
612 QRect rect = style->subControlRect(QStyle::CC_ScrollBar, &scrollBarOption,
613 QStyle::QStyle::SC_ScrollBarSlider);
614 rect.moveTopLeft(rect.topLeft() + scrollBarOption.rect.topLeft());
615 rect.moveTopLeft(rect.topLeft() + option.rect.bottomRight() - scrollBarOption.rect.bottomRight());
616 return rect;
617}
618
619QRect StoryboardDelegate::scrollDownButton(const QStyleOptionViewItem &option, QStyleOptionSlider &scrollBarOption)
620{
621 QStyle *style = option.widget ? option.widget->style() : QApplication::style();
622 QRect rect = style->subControlRect(QStyle::CC_ScrollBar, &scrollBarOption,
623 QStyle::QStyle::SC_ScrollBarAddLine);
624 rect.moveTopLeft(rect.topLeft() + scrollBarOption.rect.topLeft());
625 rect.moveBottomRight(option.rect.bottomRight());
626 return rect;
627}
628
629QRect StoryboardDelegate::scrollUpButton(const QStyleOptionViewItem &option, QStyleOptionSlider &scrollBarOption)
630{
631 QStyle *style = option.widget ? option.widget->style() : QApplication::style();
632 QRect rect = style->subControlRect(QStyle::CC_ScrollBar, &scrollBarOption,
633 QStyle::QStyle::SC_ScrollBarSubLine);
634 rect.moveTopLeft(rect.topLeft() + scrollBarOption.rect.topLeft());
635 rect.moveTop(option.rect.bottom() - scrollBarOption.rect.height());
636 rect.moveRight(option.rect.right());
637 return rect;
638}
639
641{
642 m_imageSize = imageSize;
643}
644
645bool StoryboardDelegate::isOverlappingActionIcons(const QRect &rect, const QMouseEvent *event)
646{
647 QRect addItemButton(QPoint(0, 0), QSize(22, 22));
648 addItemButton.moveBottomLeft(rect.bottomLeft());
649
650 QRect deleteItemButton(QPoint(0, 0), QSize(22, 22));
651 deleteItemButton.moveBottomRight(rect.bottomRight());
652
653 bool addItemButtonHover = addItemButton.isValid() && addItemButton.contains(event->pos());
654 bool deleteItemButtonHover = deleteItemButton.isValid() && deleteItemButton.contains(event->pos());
655
656 return addItemButtonHover || deleteItemButtonHover;
657}
658
659bool StoryboardDelegate::eventFilter(QObject *editor, QEvent *event)
660{
661 if (event->type() == QEvent::KeyPress) {
662 QKeyEvent* kEvent = static_cast<QKeyEvent*>(event);
663 QTextEdit* textEditor = qobject_cast<QTextEdit*>(editor);
664 if (textEditor && kEvent->key() == Qt::Key_Escape) {
665 Q_EMIT commitData(textEditor);
666 Q_EMIT closeEditor(textEditor, QAbstractItemDelegate::SubmitModelCache);
667 return true;
668 }
669 }
670 QStyledItemDelegate::eventFilter(editor, event);
671 return false;
672}
float value(const T *src, size_t ch)
const Params2D p
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
StoryboardDelegate(QObject *parent)
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
void setEditorData(QWidget *editor, const QModelIndex &index) const override
QStyleOptionSlider drawCommentHeader(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
Draw the comment header.
void setView(StoryboardView *view)
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override
QRect scrollDownButton(const QStyleOptionViewItem &option, QStyleOptionSlider &scrollBarOption)
QRect scrollBar(const QStyleOptionViewItem &option, QStyleOptionSlider &scrollBarOption) const
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override
QRect spinBoxEditField(const QStyleOptionViewItem &option)
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override
void slotCommentScrolledTo(int value) const
updates the scroll value of the CommentBox in StoryboardModel This enables the model to keep track of...
bool eventFilter(QObject *editor, QEvent *event) override
void drawSpinBox(QPainter *p, const QStyleOptionViewItem &option, QString data, QString suffix) const
Draw the spin box.
QRect spinBoxUpButton(const QStyleOptionViewItem &option)
bool isOverlappingActionIcons(const QRect &rect, const QMouseEvent *event)
bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override
QRect spinBoxDownButton(const QStyleOptionViewItem &option)
QRect scrollUpButton(const QStyleOptionViewItem &option, QStyleOptionSlider &scrollBarOption)
StoryboardView * m_view
void setImageSize(QSize imageSize)
@ DurationFrame
Store the duration in frame at index 3. Data type stored here should be int.
@ FrameNumber
Store the frame number at index 0. Data type stored here should be ThumbnailData.
@ DurationSecond
Store the duration in second at index 2. Data type stored here should be int.
@ ItemName
Store the item name at index 1. Data type stored here should be string.
@ Comments
Store the comments at indices greater_than_or_equal_to to index 4. Data type stored here should be Co...
The main storyboard model. This class manages a StoryboardItemList which is a list of StoryboardItem ...
bool setCommentScrollData(const QModelIndex &index, const QVariant &value)
Sets the scrollValue of the CommentBox object.
StoryboardItemList getData()
StoryboardComment getComment(int row) const
bool insertItem(QModelIndex index, bool after)
inserts item after or before index based on after parameter
void pushUndoCommand(KUndo2Command *command)
bool removeItem(QModelIndex index, KUndo2Command *command=nullptr)
removes item, deletes keyframes within and shifts keyframe after the scene to fill in the gap
int visibleCommentCount() const
Used in StoryboardDelegate and StoryboardView to get size of one storyboard item.
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
Qt::Orientation itemOrientation()
whether Comments are below or on the right of Thumbnail
bool thumbnailIsVisible() const
bool commentIsVisible() const
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129
#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)