Krita Source Code Documentation
Loading...
Searching...
No Matches
KisAnimCurvesView Class Reference

#include <KisAnimCurvesView.h>

+ Inheritance diagram for KisAnimCurvesView:

Classes

struct  Private
 

Public Slots

void applyBezierMode ()
 
void applyConstantMode ()
 
void applyLinearMode ()
 
void applySharpMode ()
 
void applySmoothMode ()
 
void changeZoom (Qt::Orientation orientation, qreal zoomDelta)
 
void createKeyframe ()
 
void removeKeyframes ()
 
void slotScrollerStateChanged (QScroller::State state)
 
void zoomToFitChannel ()
 
void zoomToFitCurve ()
 

Signals

void activeDataChanged (const QModelIndex &index)
 

Public Member Functions

QModelIndex indexAt (const QPoint &point) const override
 
bool indexHasKey (const QModelIndex &index)
 
 KisAnimCurvesView (QWidget *parent)
 
void scrollTo (const QModelIndex &index, ScrollHint hint) override
 
void setModel (QAbstractItemModel *model) override
 
QRect visualRect (const QModelIndex &index) const override
 
 ~KisAnimCurvesView () override
 

Protected Slots

void updateGeometries () override
 

Protected Member Functions

int horizontalOffset () const override
 
bool isIndexHidden (const QModelIndex &index) const override
 
void mouseDoubleClickEvent (QMouseEvent *) override
 
void mouseMoveEvent (QMouseEvent *) override
 
void mousePressEvent (QMouseEvent *) override
 
void mouseReleaseEvent (QMouseEvent *) override
 
QModelIndex moveCursor (CursorAction cursorAction, Qt::KeyboardModifiers modifiers) override
 
void paintEvent (QPaintEvent *event) override
 
void scrollContentsBy (int dx, int dy) override
 
void setSelection (const QRect &rect, QItemSelectionModel::SelectionFlags flags) override
 
int verticalOffset () const override
 
QRegion visualRegionForSelection (const QItemSelection &selection) const override
 

Private Slots

void slotDataAdded (const QModelIndex &index)
 
void slotDataChanged (const QModelIndex &topLeft, const QModelIndex &bottomRight)
 
void slotHeaderDataChanged (Qt::Orientation orientation, int first, int last)
 
void slotRowsChanged (const QModelIndex &parentIndex, int first, int last)
 
void slotUpdateHorizontalScrollbarSize ()
 
void slotUpdateInfiniteFramesCount ()
 

Private Member Functions

void findExtremes (qreal *minimum, qreal *maximum)
 
QModelIndex findNextKeyframeIndex (int channel, int time, int selectionOffset, bool backward)
 
void paintCurve (int channel, int firstFrame, int lastFrame, QPainter &painter)
 
void paintCurves (QPainter &painter, int firstFrame, int lastFrame)
 
void paintCurveSegment (QPainter &painter, QPointF pos1, QPointF rightTangent, QPointF leftTangent, QPointF pos2, QVariant limitData)
 
void paintGrid (QPainter &painter)
 
void paintKeyframes (QPainter &painter, int firstFrame, int lastFrame)
 

Private Attributes

const QScopedPointer< Privatem_d
 

Detailed Description

Definition at line 17 of file KisAnimCurvesView.h.

Constructor & Destructor Documentation

◆ KisAnimCurvesView()

KisAnimCurvesView::KisAnimCurvesView ( QWidget * parent)

Definition at line 58 of file KisAnimCurvesView.cpp.

59 : QAbstractItemView(parent)
60 , m_d(new Private())
61{
62 m_d->horizontalHeader = new KisAnimTimelineTimeHeader(this);
63
64 m_d->verticalHeader = new KisAnimCurvesValuesHeader(this);
65 m_d->itemDelegate = new KisAnimCurvesKeyDelegate(m_d->horizontalHeader, m_d->verticalHeader, this);
66
67 m_d->modifiersCatcher = new KisCustomModifiersCatcher(this);
68 m_d->modifiersCatcher->addModifier("pan-zoom", Qt::Key_Space);
69
70 setSelectionMode(QAbstractItemView::ExtendedSelection);
71
72 KisZoomableScrollBar* horiZoomableBar = new KisZoomableScrollBar(this);
73 setHorizontalScrollBar(horiZoomableBar);
74 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
75 setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
76
77 connect(horiZoomableBar, &KisZoomableScrollBar::valueChanged, [this](qreal value){
78 m_d->horizontalHeader->setPixelOffset(value);
80 viewport()->update();
81 });
82
83 connect(horiZoomableBar, &KisZoomableScrollBar::sliderReleased, this, &KisAnimCurvesView::slotUpdateHorizontalScrollbarSize);
84
85 connect(horiZoomableBar, &KisZoomableScrollBar::overscroll, [this](qreal overscroll){
86 m_d->horizontalHeader->setPixelOffset(m_d->horizontalHeader->offset() + overscroll);
89 viewport()->update();
90 });
91
92 connect(horiZoomableBar, &KisZoomableScrollBar::zoom, [this](qreal zoomDelta){
93 qreal currentZoomLevel = m_d->horizontalHeader->zoom();
94 m_d->horizontalHeader->setZoom(currentZoomLevel + zoomDelta);
97 viewport()->update();
98 });
99
100
101 KisZoomableScrollBar* vertZoomableBar = new KisZoomableScrollBar(this);
102 setVerticalScrollBar(vertZoomableBar);
103 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
104 setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
105 vertZoomableBar->setWheelOverscrollSensitivity( 0.04f );
106
107 connect(vertZoomableBar, &KisZoomableScrollBar::zoom, [this](qreal zoomDelta){
108 const qreal currentZoomLevel = m_d->verticalHeader->scale();
109 m_d->verticalHeader->setScale(currentZoomLevel + zoomDelta / m_d->verticalHeader->step());
110 });
111
112 connect(vertZoomableBar, &KisZoomableScrollBar::overscroll, [this](qreal overscroll){
113 qreal currentOffset = m_d->verticalHeader->valueOffset();
114 m_d->verticalHeader->setValueOffset(currentOffset - overscroll * m_d->verticalHeader->step() * 0.25);
115 });
116
117 connect(m_d->verticalHeader, &KisAnimCurvesValuesHeader::scaleChanged, [this](qreal){
118 viewport()->update();
119 });
120
121 connect(m_d->verticalHeader, &KisAnimCurvesValuesHeader::valueOffsetChanged, [this](qreal){
122 viewport()->update();
123 });
124
125 QScroller *scroller = KisKineticScroller::createPreconfiguredScroller(this);
126 if (scroller){
127 connect(scroller, SIGNAL(stateChanged(QScroller::State)),
128 this, SLOT(slotScrollerStateChanged(QScroller::State)));
129
130 QScrollerProperties props = scroller->scrollerProperties();
131 props.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QScrollerProperties::OvershootAlwaysOff);
132 props.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QScrollerProperties::OvershootAlwaysOff);
133 scroller->setScrollerProperties(props);
134 }
135}
float value(const T *src, size_t ch)
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
void valueOffsetChanged(qreal offset)
void scaleChanged(qreal scale)
const QScopedPointer< Private > m_d
void slotScrollerStateChanged(QScroller::State state)
The KisCustomModifiersCatcher class is a special utility class that tracks custom modifiers pressed....
void overscroll(qreal delta)
void zoom(qreal delta)
KRITAWIDGETUTILS_EXPORT QScroller * createPreconfiguredScroller(QAbstractScrollArea *target)

References connect(), KisKineticScroller::createPreconfiguredScroller(), m_d, KisZoomableScrollBar::overscroll(), KisAnimCurvesValuesHeader::scaleChanged(), slotScrollerStateChanged(), slotUpdateHorizontalScrollbarSize(), slotUpdateInfiniteFramesCount(), value(), KisAnimCurvesValuesHeader::valueOffsetChanged(), and KisZoomableScrollBar::zoom().

◆ ~KisAnimCurvesView()

KisAnimCurvesView::~KisAnimCurvesView ( )
override

Definition at line 137 of file KisAnimCurvesView.cpp.

138{}

Member Function Documentation

◆ activeDataChanged

void KisAnimCurvesView::activeDataChanged ( const QModelIndex & index)
signal

◆ applyBezierMode

void KisAnimCurvesView::applyBezierMode ( )
slot

Definition at line 886 of file KisAnimCurvesView.cpp.

887{
888 m_d->model->beginCommand(kundo2_i18n("Set interpolation mode"));
889 Q_FOREACH(QModelIndex index, selectedIndexes()) {
891 }
892 m_d->model->endCommand();
893}
KUndo2MagicString kundo2_i18n(const char *text)

References KisScalarKeyframe::Bezier, KisAnimCurvesModel::InterpolationModeRole, kundo2_i18n(), and m_d.

◆ applyConstantMode

void KisAnimCurvesView::applyConstantMode ( )
slot

Definition at line 868 of file KisAnimCurvesView.cpp.

869{
870 m_d->model->beginCommand(kundo2_i18n("Set interpolation mode"));
871 Q_FOREACH(QModelIndex index, selectedIndexes()) {
873 }
874 m_d->model->endCommand();
875}

References KisScalarKeyframe::Constant, KisAnimCurvesModel::InterpolationModeRole, kundo2_i18n(), and m_d.

◆ applyLinearMode

void KisAnimCurvesView::applyLinearMode ( )
slot

Definition at line 877 of file KisAnimCurvesView.cpp.

878{
879 m_d->model->beginCommand(kundo2_i18n("Set interpolation mode"));
880 Q_FOREACH(QModelIndex index, selectedIndexes()) {
882 }
883 m_d->model->endCommand();
884}

References KisAnimCurvesModel::InterpolationModeRole, kundo2_i18n(), KisScalarKeyframe::Linear, and m_d.

◆ applySharpMode

void KisAnimCurvesView::applySharpMode ( )
slot

Definition at line 923 of file KisAnimCurvesView.cpp.

924{
925 m_d->model->beginCommand(kundo2_i18n("Set interpolation mode"));
926 Q_FOREACH(QModelIndex index, selectedIndexes()) {
928 }
929 m_d->model->endCommand();
930}

References kundo2_i18n(), m_d, KisScalarKeyframe::Sharp, and KisAnimCurvesModel::TangentsModeRole.

◆ applySmoothMode

void KisAnimCurvesView::applySmoothMode ( )
slot

Definition at line 895 of file KisAnimCurvesView.cpp.

896{
897 m_d->model->beginCommand(kundo2_i18n("Set interpolation mode"));
898 Q_FOREACH(QModelIndex index, selectedIndexes()) {
899 QVector2D leftVisualTangent(m_d->itemDelegate->leftHandle(index, false));
900 QVector2D rightVisualTangent(m_d->itemDelegate->rightHandle(index, false));
901
902 if (leftVisualTangent.lengthSquared() > 0 && rightVisualTangent.lengthSquared() > 0) {
903 float leftAngle = qAtan2(-leftVisualTangent.y(), -leftVisualTangent.x());
904 float rightAngle = qAtan2(rightVisualTangent.y(), rightVisualTangent.x());
905 float angle = (leftAngle + rightAngle) / 2;
906 QVector2D unit(qCos(angle), qSin(angle));
907
908 leftVisualTangent = -unit * QVector2D(leftVisualTangent).length();
909 rightVisualTangent = unit * QVector2D(rightVisualTangent).length();
910
911 QPointF leftTangent = m_d->itemDelegate->unscaledTangent(leftVisualTangent.toPointF());
912 QPointF rightTangent = m_d->itemDelegate->unscaledTangent(rightVisualTangent.toPointF());
913
914 model()->setData(index, leftTangent, KisAnimCurvesModel::LeftTangentRole);
915 model()->setData(index, rightTangent, KisAnimCurvesModel::RightTangentRole);
916 }
917
919 }
920 m_d->model->endCommand();
921}

References kundo2_i18n(), KisAnimCurvesModel::LeftTangentRole, m_d, KisAnimCurvesModel::RightTangentRole, KisScalarKeyframe::Smooth, and KisAnimCurvesModel::TangentsModeRole.

◆ changeZoom

void KisAnimCurvesView::changeZoom ( Qt::Orientation orientation,
qreal zoomDelta )
slot

Definition at line 994 of file KisAnimCurvesView.cpp.

995{
996 if (orientation == Qt::Horizontal) {
997 m_d->horizontalHeader->setZoom( m_d->horizontalHeader->zoom() + zoomDelta);
999 } else {
1000 const qreal currentZoomLevel = m_d->verticalHeader->scale();
1001 m_d->verticalHeader->setScale(currentZoomLevel + zoomDelta / m_d->verticalHeader->step());
1002 }
1003 viewport()->update();
1004}

References m_d, and slotUpdateInfiniteFramesCount().

◆ createKeyframe

void KisAnimCurvesView::createKeyframe ( )
slot

Definition at line 932 of file KisAnimCurvesView.cpp.

933{
934 QModelIndex active = currentIndex();
935 int channel = active.isValid() ? active.row() : 0;
936
937 int time = m_d->model->currentTime();
938 QModelIndex index = m_d->model->index(channel, time);
939
940 qreal value = index.data(KisAnimCurvesModel::ScalarValueRole).toReal();
941 m_d->model->setData(index, value, KisAnimCurvesModel::ScalarValueRole);
942}

References m_d, KisAnimCurvesModel::ScalarValueRole, and value().

◆ findExtremes()

void KisAnimCurvesView::findExtremes ( qreal * minimum,
qreal * maximum )
private

Definition at line 419 of file KisAnimCurvesView.cpp.

420{
421 if (!model()) return;
422
423 qreal min = qInf();
424 qreal max = -qInf();
425
426 int curveCount = model()->rowCount();
427 for (int curveIndex = 0; curveIndex < curveCount; curveIndex++) {
428 QModelIndex index = model()->index(curveIndex, 0);
429 if (isIndexHidden(index)) continue;
430
431 QVariant nextTime;
432 do {
433 qreal value = index.data(KisAnimCurvesModel::ScalarValueRole).toReal();
434
435 if (value < min) min = value;
436 if (value > max) max = value;
437
438 const int MAX_NUM_TANGENTS = 2;
439 for (int i = 0; i < MAX_NUM_TANGENTS; i++) {
440 QVariant tangent = index.data(KisAnimCurvesModel::LeftTangentRole + i);
441 if (!tangent.isValid())
442 continue;
443
444 QPointF tangentPointF = tangent.toPointF();
445 if (value + tangentPointF.y() < min) min = value + tangentPointF.y();
446 if (value + tangentPointF.y() > max) max = value + tangentPointF.y();
447 }
448
449 nextTime = index.data(KisAnimCurvesModel::NextKeyframeTime);
450 if (nextTime.isValid()) index = model()->index(curveIndex, nextTime.toInt());
451 } while (nextTime.isValid());
452 }
453
454 if (qIsFinite(min)) *minimum = min;
455 if (qIsFinite(max)) *maximum = max;
456}
bool isIndexHidden(const QModelIndex &index) const override
T min(T a, T b, T c)
constexpr std::enable_if< sizeof...(values)==0, size_t >::type max()

References isIndexHidden(), KisAnimCurvesModel::LeftTangentRole, KisAnimCurvesModel::NextKeyframeTime, KisAnimCurvesModel::ScalarValueRole, and value().

◆ findNextKeyframeIndex()

QModelIndex KisAnimCurvesView::findNextKeyframeIndex ( int channel,
int time,
int selectionOffset,
bool backward )
private

Definition at line 380 of file KisAnimCurvesView.cpp.

381{
384 QModelIndex currentIndex = model()->index(channel, time);
385
386 if (!selectionOffset) {
387 QVariant next = currentIndex.data(role);
388 return (next.isValid()) ? model()->index(channel, next.toInt()) : QModelIndex();
389 } else {
390 // Find the next unselected index
391 QModelIndex nextIndex = currentIndex;
392 do {
393 QVariant next = nextIndex.data(role);
394 nextIndex = (next.isValid()) ? model()->index(channel, next.toInt()) : QModelIndex();
395 } while(nextIndex.isValid() && selectionModel()->isSelected(nextIndex));
396
397 // Find the next selected index, accounting for D&D offset
398 QModelIndex draggedIndex = model()->index(channel, qMax(0, time - selectionOffset));
399 do {
400 QVariant next = draggedIndex.data(role);
401 draggedIndex = (next.isValid()) ? model()->index(channel, next.toInt()) : QModelIndex();
402 } while(draggedIndex.isValid() && !selectionModel()->isSelected(draggedIndex));
403
404 // Choose the earlier of the two
405 if (draggedIndex.isValid() && nextIndex.isValid()) {
406 if (draggedIndex.column() + selectionOffset <= nextIndex.column()) {
407 return draggedIndex;
408 } else {
409 return nextIndex;
410 }
411 } else if (draggedIndex.isValid()) {
412 return draggedIndex;
413 } else {
414 return nextIndex;
415 }
416 }
417}
QAction * next(const QObject *recvr, const char *slot, QObject *parent)

References KisAnimCurvesModel::NextKeyframeTime, and KisAnimCurvesModel::PreviousKeyframeTime.

◆ horizontalOffset()

int KisAnimCurvesView::horizontalOffset ( ) const
overrideprotected

Definition at line 466 of file KisAnimCurvesView.cpp.

467{
468 return m_d->horizontalHeader->offset();
469}

References m_d.

◆ indexAt()

QModelIndex KisAnimCurvesView::indexAt ( const QPoint & point) const
override

Definition at line 184 of file KisAnimCurvesView.cpp.

185{
186 if (!model()) return QModelIndex();
187
188 int time = m_d->horizontalHeader->logicalIndexAt(point.x());
189
190 int rows = model()->rowCount();
191 for (int row=0; row < rows; row++) {
192 QModelIndex index = model()->index(row, time);
193
194 if (index.data(KisTimeBasedItemModel::SpecialKeyframeExists).toBool()
195 && index.data(KisAnimCurvesModel::CurveVisibleRole).toBool()) {
196 QRect nodePos = m_d->itemDelegate->itemRect(index);
197
198 if (nodePos.contains(point)) {
199 return index;
200 }
201 }
202 }
203
204 return QModelIndex();
205}

References KisAnimCurvesModel::CurveVisibleRole, m_d, and KisTimeBasedItemModel::SpecialKeyframeExists.

◆ indexHasKey()

bool KisAnimCurvesView::indexHasKey ( const QModelIndex & index)

Definition at line 770 of file KisAnimCurvesView.cpp.

771{
772 const QVariant data = m_d->model->data(index, KisAnimCurvesModel::SpecialKeyframeExists);
773 return data.isValid() && data.toBool();
774}

References m_d, and KisTimeBasedItemModel::SpecialKeyframeExists.

◆ isIndexHidden()

bool KisAnimCurvesView::isIndexHidden ( const QModelIndex & index) const
overrideprotected

Definition at line 476 of file KisAnimCurvesView.cpp.

477{
478 return !index.data(KisAnimCurvesModel::CurveVisibleRole).toBool();
479}

References KisAnimCurvesModel::CurveVisibleRole.

◆ mouseDoubleClickEvent()

void KisAnimCurvesView::mouseDoubleClickEvent ( QMouseEvent * e)
overrideprotected

Definition at line 591 of file KisAnimCurvesView.cpp.

592{
593 QModelIndex clicked = indexAt(e->pos());
594
595 if(clicked.isValid() && indexHasKey(clicked)) {
596 selectionModel()->clear();
597 bool firstSelection = true;
598 if (e->modifiers() & Qt::AltModifier) {
599 for (int column = 0; column <= model()->columnCount(); column++) {
600 QModelIndex toSelect = model()->index(clicked.row(), column);
601 const bool hasSpecial = toSelect.data(KisTimeBasedItemModel::SpecialKeyframeExists).toBool();
602 const bool curveVisible = toSelect.data(KisAnimCurvesModel::CurveVisibleRole).toBool();
603 if (toSelect.isValid() && hasSpecial && curveVisible) {
604 selectionModel()->select(toSelect, firstSelection ? QItemSelectionModel::SelectCurrent : QItemSelectionModel::Select);
605 firstSelection = false;
606 }
607 }
608 } else {
609 for (int row = 0; row <= model()->rowCount(); row++) {
610 QModelIndex toSelect = model()->index(row, clicked.column());
611 const bool hasSpecial = toSelect.data(KisTimeBasedItemModel::SpecialKeyframeExists).toBool();
612 const bool curveVisible = toSelect.data(KisAnimCurvesModel::CurveVisibleRole).toBool();
613 if (toSelect.isValid() && hasSpecial && curveVisible) {
614 selectionModel()->select(toSelect, firstSelection ? QItemSelectionModel::SelectCurrent : QItemSelectionModel::Select);
615 firstSelection = false;
616 }
617 }
618 }
619
620 QModelIndex oldCurrent = selectionModel()->currentIndex();
621 selectionModel()->setCurrentIndex(clicked, QItemSelectionModel::NoUpdate);
622 currentChanged(clicked, oldCurrent);
623 } else {
624 QAbstractItemView::mouseDoubleClickEvent(e);
625 }
626}
bool indexHasKey(const QModelIndex &index)
QModelIndex indexAt(const QPoint &point) const override

References KisAnimCurvesModel::CurveVisibleRole, indexAt(), indexHasKey(), and KisTimeBasedItemModel::SpecialKeyframeExists.

◆ mouseMoveEvent()

void KisAnimCurvesView::mouseMoveEvent ( QMouseEvent * e)
overrideprotected

Definition at line 628 of file KisAnimCurvesView.cpp.

629{
630 if (m_d->modifiersCatcher->modifierPressed("pan-zoom")) {
631 if (m_d->dragPanning) {
632 const int timelineScrubAmnt = m_d->panAnchor.x() - e->pos().x();
633 const qreal valueScrubAmnt = m_d->verticalHeader->pixelsToValueOffset(m_d->panAnchor.y() - e->pos().y());
634
637 horizontalScrollBar()->setValue(horizontalScrollBar()->value() + timelineScrubAmnt);
638
639 m_d->verticalHeader->setValueOffset(m_d->verticalHeader->valueOffset() + valueScrubAmnt);
640
641 m_d->panAnchor = e->pos();
642 viewport()->update();
643 return;
644 }
645
646 if (m_d->dragZooming) {
647 const qreal zoomScale = 50.0f;
648 const qreal updown = ((m_d->zoomAnchor.y() - e->pos().y())) / zoomScale;
649 const qreal leftright = (m_d->zoomAnchor.x() - e->pos().x()) / zoomScale;
650
651 changeZoom(Qt::Vertical, updown);
652 changeZoom(Qt::Horizontal, leftright * -0.5);
653
654 m_d->zoomAnchor = e->pos();
655 viewport()->update();
656 return;
657 }
658
659 } else if (e->buttons() & Qt::LeftButton) {
660
661 m_d->dragOffset = e->pos() - m_d->dragStart;
662
663 if (m_d->isAdjustingHandle) {
664 m_d->itemDelegate->setHandleAdjustment(m_d->dragOffset, m_d->adjustedHandle);
665 viewport()->update();
666 return;
667 } else if (m_d->isDraggingKeyframe) {
668 const bool axisSnap = (e->modifiers() & Qt::ShiftModifier);
669 m_d->itemDelegate->setSelectedItemVisualOffset(m_d->dragOffset, axisSnap);
670 viewport()->update();
671 return;
672 } else if (selectionModel()->hasSelection()) {
673 if ((e->pos() - m_d->dragStart).manhattanLength() > QApplication::startDragDistance()) {
674 m_d->isDraggingKeyframe = true;
675 }
676 }
677 } else {
678 QAbstractItemView::mouseMoveEvent(e);
679 }
680}
void changeZoom(Qt::Orientation orientation, qreal zoomDelta)

References changeZoom(), m_d, slotUpdateHorizontalScrollbarSize(), slotUpdateInfiniteFramesCount(), and value().

◆ mousePressEvent()

void KisAnimCurvesView::mousePressEvent ( QMouseEvent * e)
overrideprotected

Definition at line 525 of file KisAnimCurvesView.cpp.

526{
527 if (m_d->modifiersCatcher->modifierPressed("pan-zoom")) {
528 if (e->button() == Qt::LeftButton) { // PAN
529 m_d->dragPanning = true;
530 m_d->panAnchor = e->pos();
531
532 } else if (e->button() == Qt::RightButton) { // ZOOM
533 m_d->dragZooming = true;
534 m_d->zoomAnchor = e->pos();
535 }
536 } else if (e->button() == Qt::LeftButton) { // SELECT
537 m_d->dragStart = e->pos();
538
539 const int handleClickRadius = 16;
540
541 Q_FOREACH(QModelIndex index, selectedIndexes()) {
542
543 if (isIndexHidden(index)) continue;
544
545 QPointF center = m_d->itemDelegate->nodeCenter(index, false);
546 bool hasLeftHandle = m_d->itemDelegate->hasHandle(index, 0);
547 bool hasRightHandle = m_d->itemDelegate->hasHandle(index, 1);
548
549 QPointF leftHandle = center + m_d->itemDelegate->leftHandle(index, false);
550 QPointF rightHandle = center + m_d->itemDelegate->rightHandle(index, false);
551
552 if (hasLeftHandle && (e->localPos() - leftHandle).manhattanLength() < handleClickRadius) {
553 m_d->isAdjustingHandle = true;
554 m_d->adjustedHandle = 0;
555 setCurrentIndex(index);
556 continue;
557 } else if (hasRightHandle && (e->localPos() - rightHandle).manhattanLength() < handleClickRadius) {
558 m_d->isAdjustingHandle = true;
559 m_d->adjustedHandle = 1;
560 setCurrentIndex(index);
561 continue;
562 }
563 }
564
565 }
566
567 QModelIndex clickedIndex = indexAt(e->pos());
568 if(indexHasKey(clickedIndex)) {
569 if ((e->modifiers() & Qt::ShiftModifier) == 0 && selectionModel()->currentIndex() != clickedIndex) {
570 clearSelection();
571 }
572
573 if (clickedIndex == selectionModel()->currentIndex() && selectionModel()->hasSelection()) {
574 m_d->deselectIntended = true;
575 m_d->toDeselect = clickedIndex;
576 } else {
577 QModelIndex prevCurrent = selectionModel()->currentIndex();
578 selectionModel()->select(clickedIndex, QItemSelectionModel::Select);
579 selectionModel()->setCurrentIndex(clickedIndex, QItemSelectionModel::NoUpdate);
580 Q_EMIT currentChanged(clickedIndex, prevCurrent);
581 }
582
583 Q_EMIT clicked(clickedIndex);
584 Q_EMIT activeDataChanged(selectionModel()->currentIndex());
585 } else {
586 QAbstractItemView::mousePressEvent(e);
587 }
588}
void activeDataChanged(const QModelIndex &index)

References activeDataChanged(), indexAt(), indexHasKey(), isIndexHidden(), and m_d.

◆ mouseReleaseEvent()

void KisAnimCurvesView::mouseReleaseEvent ( QMouseEvent * e)
overrideprotected

Definition at line 682 of file KisAnimCurvesView.cpp.

683{
684
685 if (e->button() == Qt::LeftButton) {
686 m_d->dragPanning = false;
687 m_d->dragZooming = false;
688
689 if (m_d->isDraggingKeyframe) {
690 const QModelIndexList indices = selectedIndexes();
691 const QPointF largestOffset = qAbs(m_d->dragOffset.y()) > qAbs(m_d->dragOffset.x()) ? QPointF(0.0f, m_d->dragOffset.y()) :
692 QPointF(m_d->dragOffset.x(), 0.0f);
693
694 //Only use the largest offset when axis snap is enabled on mouse button release..
695 const bool axisSnap = (e->modifiers() & Qt::ShiftModifier);
696 const QPointF offset = axisSnap ? largestOffset : m_d->dragOffset;
697 const int timeOffset = qRound( qreal(offset.x()) / m_d->horizontalHeader->defaultSectionSize() );
698 const qreal valueOffset = m_d->verticalHeader->pixelsToValueOffset(offset.y());
699
700 KisAnimCurvesModel *curvesModel = dynamic_cast<KisAnimCurvesModel*>(model());
702 curvesModel->adjustKeyframes(indices, timeOffset, valueOffset);
703
704 //Adjust selection to match new keyframe adjustment.
705 Q_FOREACH(const QModelIndex& index, indices) {
706 const bool wasCurrent = (index == selectionModel()->currentIndex());
707 selectionModel()->select(index, QItemSelectionModel::Deselect);
708 const QModelIndex newIndex = m_d->model->index(index.row(), index.column() + timeOffset);
709 if (wasCurrent) {
710 selectionModel()->setCurrentIndex(newIndex, QItemSelectionModel::SelectCurrent);
711 } else {
712 selectionModel()->select(newIndex, QItemSelectionModel::Select);
713 }
714 }
715
716 m_d->isDraggingKeyframe = false;
717 m_d->itemDelegate->setSelectedItemVisualOffset(QPointF());
718 viewport()->update();
719 } else if (m_d->isAdjustingHandle) {
720 QModelIndex index = currentIndex();
721 int mode = index.data(KisAnimCurvesModel::TangentsModeRole).toInt();
722
723 m_d->model->beginCommand(kundo2_i18n("Adjust tangent"));
724
725 if (mode == KisScalarKeyframe::Smooth) {
726 QPointF leftHandle = m_d->itemDelegate->leftHandle(index, true);
727 QPointF rightHandle = m_d->itemDelegate->rightHandle(index, true);
728
729 QPointF leftTangent = m_d->itemDelegate->unscaledTangent(leftHandle);
730 QPointF rightTangent = m_d->itemDelegate->unscaledTangent(rightHandle);
731
732 model()->setData(index, leftTangent, KisAnimCurvesModel::LeftTangentRole);
733 model()->setData(index, rightTangent, KisAnimCurvesModel::RightTangentRole);
734 } else {
735 if (m_d->adjustedHandle == 0) {
736 QPointF leftHandle = m_d->itemDelegate->leftHandle(index, true);
737 model()->setData(index, m_d->itemDelegate->unscaledTangent(leftHandle), KisAnimCurvesModel::LeftTangentRole);
738 } else {
739 QPointF rightHandle = m_d->itemDelegate->rightHandle(index, true);
740 model()->setData(index, m_d->itemDelegate->unscaledTangent(rightHandle), KisAnimCurvesModel::RightTangentRole);
741 }
742 }
743
744 m_d->model->endCommand();
745
746 m_d->isAdjustingHandle = false;
747 m_d->itemDelegate->setHandleAdjustment(QPointF(), m_d->adjustedHandle);
748 } else {
749
750 if (m_d->deselectIntended){
751 selectionModel()->select(m_d->toDeselect, QItemSelectionModel::Deselect);
752 }
753
754 }
755
756 m_d->deselectIntended = false;
757 m_d->toDeselect = QModelIndex();
758 }
759
760 QAbstractItemView::mouseReleaseEvent(e);
761}
bool adjustKeyframes(const QModelIndexList &indexes, int timeOffset, qreal valueOffset)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128

References KisAnimCurvesModel::adjustKeyframes(), KIS_SAFE_ASSERT_RECOVER_RETURN, kundo2_i18n(), KisAnimCurvesModel::LeftTangentRole, m_d, KisAnimCurvesModel::RightTangentRole, KisScalarKeyframe::Smooth, and KisAnimCurvesModel::TangentsModeRole.

◆ moveCursor()

QModelIndex KisAnimCurvesView::moveCursor ( CursorAction cursorAction,
Qt::KeyboardModifiers modifiers )
overrideprotected

Definition at line 458 of file KisAnimCurvesView.cpp.

459{
460 // TODO
461 Q_UNUSED(cursorAction);
462 Q_UNUSED(modifiers);
463 return QModelIndex();
464}

◆ paintCurve()

void KisAnimCurvesView::paintCurve ( int channel,
int firstFrame,
int lastFrame,
QPainter & painter )
private

Definition at line 294 of file KisAnimCurvesView.cpp.

295{
296 int selectionOffset = m_d->isDraggingKeyframe ? (m_d->dragOffset.x() / m_d->horizontalHeader->defaultSectionSize()) : 0;
297
298 QModelIndex index = findNextKeyframeIndex(channel, firstFrame+1, selectionOffset, true);
299 if (!index.isValid()) {
300 index = findNextKeyframeIndex(channel, firstFrame, selectionOffset, false);
301 }
302 if (!index.isValid()) return;
303
304 QPointF previousKeyPos = m_d->itemDelegate->nodeCenter(index, selectionModel()->isSelected(index));
305 QPointF rightTangent = m_d->itemDelegate->rightHandle(index, index == currentIndex());
306
307 while(index.column() <= lastFrame) {
308 int interpolationMode = index.data(KisAnimCurvesModel::InterpolationModeRole).toInt();
309
310 int time = (m_d->isDraggingKeyframe && selectionModel()->isSelected(index)) ? index.column() + selectionOffset : index.column();
311 index = findNextKeyframeIndex(channel, time, selectionOffset, false);
312 if (!index.isValid()) return;
313
314 bool active = (index == currentIndex());
315 QPointF nextKeyPos = m_d->itemDelegate->nodeCenter(index, selectionModel()->isSelected(index));
316 QPointF leftTangent = m_d->itemDelegate->leftHandle(index, active);
317
318 if (interpolationMode == KisScalarKeyframe::Constant) {
319 painter.drawLine(previousKeyPos, QPointF(nextKeyPos.x(), previousKeyPos.y()));
320 } else if (interpolationMode == KisScalarKeyframe::Linear) {
321 painter.drawLine(previousKeyPos, nextKeyPos);
322 } else {
323 QVariant limitData = m_d->model->data(m_d->model->index(channel, index.column()), KisAnimCurvesModel::ChannelLimits);
324 paintCurveSegment(painter, previousKeyPos, rightTangent, leftTangent, nextKeyPos, limitData);
325 }
326
327 previousKeyPos = nextKeyPos;
328 rightTangent = m_d->itemDelegate->rightHandle(index, active);
329 }
330}
QModelIndex findNextKeyframeIndex(int channel, int time, int selectionOffset, bool backward)
void paintCurveSegment(QPainter &painter, QPointF pos1, QPointF rightTangent, QPointF leftTangent, QPointF pos2, QVariant limitData)

References KisAnimCurvesModel::ChannelLimits, KisScalarKeyframe::Constant, findNextKeyframeIndex(), KisAnimCurvesModel::InterpolationModeRole, KisScalarKeyframe::Linear, m_d, and paintCurveSegment().

◆ paintCurves()

void KisAnimCurvesView::paintCurves ( QPainter & painter,
int firstFrame,
int lastFrame )
private

Definition at line 278 of file KisAnimCurvesView.cpp.

279{
280 int channels = model()->rowCount();
281 for (int channel = 0; channel < channels; channel++) {
282 QModelIndex index0 = model()->index(channel, 0);
283
284 if (!isIndexHidden(index0)) {
285 QColor color = index0.data(KisAnimCurvesModel::CurveColorRole).value<QColor>();
286 painter.setPen(QPen(color, 1));
287 painter.setRenderHint(QPainter::Antialiasing);
288
289 paintCurve(channel, firstFrame, lastFrame, painter);
290 }
291 }
292}
void paintCurve(int channel, int firstFrame, int lastFrame, QPainter &painter)

References KisAnimCurvesModel::CurveColorRole, isIndexHidden(), and paintCurve().

◆ paintCurveSegment()

void KisAnimCurvesView::paintCurveSegment ( QPainter & painter,
QPointF pos1,
QPointF rightTangent,
QPointF leftTangent,
QPointF pos2,
QVariant limitData )
private

Definition at line 332 of file KisAnimCurvesView.cpp.

332 {
333 const int steps = 32;
334 QPointF previousPos;
335
336 for (int step = 0; step <= steps; step++) {
337 qreal t = 1.0 * step / steps;
338
339 QPointF nextPos = KisScalarKeyframeChannel::interpolate(pos1, rightTangent, leftTangent, pos2, t);
340 if (limitData.isValid()) {
341 ChannelLimitsMetatype limits = limitData.value<ChannelLimitsMetatype>();
342
343 nextPos.setY(qMin(nextPos.y(), m_d->verticalHeader->valueToWidget(limits.first)));
344 nextPos.setY(qMax(nextPos.y(), m_d->verticalHeader->valueToWidget(limits.second)));
345 }
346
347 if (step > 0) {
348 painter.drawLine(previousPos, nextPos);
349 }
350
351 previousPos = nextPos;
352 }
353}
QPair< qreal, qreal > ChannelLimitsMetatype
static QPointF interpolate(QPointF point1, QPointF rightTangent, QPointF leftTangent, QPointF point2, qreal t)

References KisScalarKeyframeChannel::interpolate(), and m_d.

◆ paintEvent()

void KisAnimCurvesView::paintEvent ( QPaintEvent * event)
overrideprotected

Definition at line 207 of file KisAnimCurvesView.cpp.

208{
209 QPainter painter(viewport());
210
211 QRect rect = event->rect();
212 rect.translate(dirtyRegionOffset());
213
214 int firstFrame = m_d->horizontalHeader->logicalIndexAt(rect.left());
215 int lastFrame = m_d->horizontalHeader->logicalIndexAt(rect.right());
216 if (lastFrame == -1) lastFrame = model()->columnCount();
217
218 paintGrid(painter);
219 paintCurves(painter, firstFrame, lastFrame);
220 paintKeyframes(painter, firstFrame, lastFrame);
221}
void paintCurves(QPainter &painter, int firstFrame, int lastFrame)
void paintKeyframes(QPainter &painter, int firstFrame, int lastFrame)
void paintGrid(QPainter &painter)

References m_d, paintCurves(), paintGrid(), and paintKeyframes().

◆ paintGrid()

void KisAnimCurvesView::paintGrid ( QPainter & painter)
private

Definition at line 223 of file KisAnimCurvesView.cpp.

224{
225 const QColor backgroundColor = qApp->palette().window().color();
226 const QColor textColor = qApp->palette().text().color();
227 const QColor lineColor = KisPaintingTweaks::blendColors(textColor, backgroundColor, 0.1);
228 const QColor zeroLineColor = qApp->palette().highlight().color();
229 const QColor activeFrameColor = KisAnimTimelineColors::instance()->headerActive().color();
230
231 // Draw vertical lines..
232 const int visibleFrames = m_d->horizontalHeader->estimateLastVisibleColumn() - m_d->horizontalHeader->estimateFirstVisibleColumn() + 1;
233 const int firstVisibleFrame = qMax( m_d->horizontalHeader->estimateFirstVisibleColumn() - 1, 0);
234 for (int time = 0; time <= visibleFrames; time++) {
235 QVariant data = m_d->model->headerData(firstVisibleFrame + time, Qt::Horizontal, KisTimeBasedItemModel::ActiveFrameRole);
236 const bool activeFrame = data.isValid() && data.toBool();
237
238 data = m_d->model->headerData(firstVisibleFrame + time, Qt::Horizontal, KisTimeBasedItemModel::WithinClipRange);
239 const bool withinClipRange = data.isValid() && data.toBool();
240
241 const int offsetHori = m_d->horizontalHeader ? m_d->horizontalHeader->offset() : 0;
242 const int stepHori = m_d->horizontalHeader->defaultSectionSize();
243 const int xPosition = stepHori * (firstVisibleFrame + time) - offsetHori;
244
245 QRect frameRect = QRect(xPosition, -10, stepHori, 9999);
246
247 const QPoint top = frameRect.topLeft() + 0.5 * (frameRect.topRight() - frameRect.topLeft());
248 const QPoint bottom = frameRect.bottomLeft() + 0.5 * (frameRect.bottomRight() - frameRect.bottomLeft());
249
250 QColor fadedLineColor = lineColor;
251 fadedLineColor.setAlphaF(0.33);
252
253 QColor finalColor = withinClipRange ? lineColor : fadedLineColor;
254 finalColor = activeFrame ? activeFrameColor : finalColor;
255
256 painter.setPen(finalColor);
257 painter.drawLine(top, bottom);
258 }
259
260 // Draw horizontal lines..
261 const int visibleSteps = m_d->verticalHeader->visibleValueDifference() / m_d->verticalHeader->step();
262 const qreal stepAmount = m_d->verticalHeader->step();
263 for (int step = 0; step <= visibleSteps; step++) {
264 const qreal value = m_d->verticalHeader->firstVisibleStep() + stepAmount * step;
265 const int CORRECTION = -1;
266 int yPosition = m_d->verticalHeader->valueToWidget(value);
267
268 QRect frameRect = QRect(-10, yPosition + CORRECTION, 9999, 1);
269
270 const QPoint left = frameRect.topLeft();
271 const QPoint right = frameRect.topRight();
272
273 painter.setPen(value == 0 ? zeroLineColor : lineColor);
274 painter.drawLine(left, right);
275 }
276}
static KisAnimTimelineColors * instance()
QColor blendColors(const QColor &c1, const QColor &c2, qreal r1)

References KisTimeBasedItemModel::ActiveFrameRole, KisPaintingTweaks::blendColors(), KisAnimTimelineColors::headerActive(), KisAnimTimelineColors::instance(), m_d, value(), and KisTimeBasedItemModel::WithinClipRange.

◆ paintKeyframes()

void KisAnimCurvesView::paintKeyframes ( QPainter & painter,
int firstFrame,
int lastFrame )
private

Definition at line 355 of file KisAnimCurvesView.cpp.

356{
357 int channels = model()->rowCount();
358 for (int channel = 0; channel < channels; channel++) {
359 for (int time=firstFrame; time <= lastFrame; time++) {
360 QModelIndex index = model()->index(channel, time);
361 bool keyframeExists = model()->data(index, KisAnimCurvesModel::SpecialKeyframeExists).toReal();
362
363 if (keyframeExists && !isIndexHidden(index)) {
364 QStyleOptionViewItem opt;
365
366 if (selectionModel()->isSelected(index)) {
367 opt.state |= QStyle::State_Selected;
368 }
369
370 if (index == selectionModel()->currentIndex()) {
371 opt.state |= QStyle::State_HasFocus;
372 }
373
374 m_d->itemDelegate->paint(&painter, opt, index);
375 }
376 }
377 }
378}

References isIndexHidden(), m_d, and KisTimeBasedItemModel::SpecialKeyframeExists.

◆ removeKeyframes

void KisAnimCurvesView::removeKeyframes ( )
slot

Definition at line 944 of file KisAnimCurvesView.cpp.

945{
946 m_d->model->removeFrames(selectedIndexes());
947}

References m_d.

◆ scrollContentsBy()

void KisAnimCurvesView::scrollContentsBy ( int dx,
int dy )
overrideprotected

Definition at line 763 of file KisAnimCurvesView.cpp.

764{
765 scrollDirtyRegion(dx, dy);
766 viewport()->scroll(dx, dy);
767 viewport()->update();
768}

◆ scrollTo()

void KisAnimCurvesView::scrollTo ( const QModelIndex & index,
ScrollHint hint )
override

Definition at line 177 of file KisAnimCurvesView.cpp.

178{
179 // TODO
180 Q_UNUSED(index);
181 Q_UNUSED(hint);
182}

◆ setModel()

void KisAnimCurvesView::setModel ( QAbstractItemModel * model)
override

Definition at line 140 of file KisAnimCurvesView.cpp.

141{
142 m_d->model = dynamic_cast<KisAnimCurvesModel*>(model);
143
144 QAbstractItemView::setModel(model);
145 m_d->horizontalHeader->setModel(model);
146
147 connect(model, &QAbstractItemModel::rowsInserted,
149
150 connect(model, &QAbstractItemModel::rowsRemoved,
152
153 connect(model, &QAbstractItemModel::dataChanged,
155
156 connect(model, &QAbstractItemModel::headerDataChanged,
158
159 connect(selectionModel(), &QItemSelectionModel::selectionChanged,
160 [this](const QItemSelection& newSelection, const QItemSelection& /*oldSelection*/) {
161 if (newSelection.count() == 0) {
162 activeDataChanged(QModelIndex());
163 } else {
164 activeDataChanged(selectionModel()->currentIndex());
165 }
166 });
167
170}
void dataAdded(const QModelIndex &index)
void slotRowsChanged(const QModelIndex &parentIndex, int first, int last)
void slotDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
void slotDataAdded(const QModelIndex &index)
void slotHeaderDataChanged(Qt::Orientation orientation, int first, int last)

References connect(), KisAnimCurvesModel::dataAdded(), m_d, slotDataAdded(), slotDataChanged(), slotHeaderDataChanged(), and slotRowsChanged().

◆ setSelection()

void KisAnimCurvesView::setSelection ( const QRect & rect,
QItemSelectionModel::SelectionFlags flags )
overrideprotected

Definition at line 481 of file KisAnimCurvesView.cpp.

482{
483 int timeFrom = m_d->horizontalHeader->logicalIndexAt(rect.left());
484 int timeTo = m_d->horizontalHeader->logicalIndexAt(rect.right());
485
486 QItemSelection selection;
487
488 int rows = model()->rowCount();
489 for (int row=0; row < rows; row++) {
490 for (int time = timeFrom; time <= timeTo; time++) {
491
492 QModelIndex index = model()->index(row, time);
493
494 if (isIndexHidden(index)) continue;
495
496 if (index.data(KisTimeBasedItemModel::SpecialKeyframeExists).toBool()) {
497 QRect itemRect = m_d->itemDelegate->itemRect(index);
498
499 if (itemRect.intersects(rect)) {
500 selection.select(index, index);
501 }
502 }
503 }
504 }
505
506 if (!selection.contains(selectionModel()->currentIndex()) && selection.size() > 0) {
507 selectionModel()->setCurrentIndex(selection.first().topLeft(), flags);
508 }
509
510 selectionModel()->select(selection, flags);
511 activated(selectionModel()->currentIndex());
512}

References isIndexHidden(), m_d, and KisTimeBasedItemModel::SpecialKeyframeExists.

◆ slotDataAdded

void KisAnimCurvesView::slotDataAdded ( const QModelIndex & index)
privateslot

Definition at line 822 of file KisAnimCurvesView.cpp.

823{
824 const qreal lastVisibleValue = m_d->verticalHeader->visibleValueMax();
825 const qreal firstVisibleValue = m_d->verticalHeader->visibleValueMin();
826
827 qreal value = index.data(KisAnimCurvesModel::ScalarValueRole).toReal();
828 if ( value < firstVisibleValue || value > lastVisibleValue) {
829 qreal min, max;
830 findExtremes(&min, &max);
831 qreal padding = (max - min) * 0.1;
832 m_d->verticalHeader->zoomToFitRange(min - padding, max + padding);
833 viewport()->update();
834 }
835
836 selectionModel()->clear();
837 selectionModel()->setCurrentIndex(index, QItemSelectionModel::SelectCurrent);
838}
void findExtremes(qreal *minimum, qreal *maximum)

References findExtremes(), m_d, KisAnimCurvesModel::ScalarValueRole, and value().

◆ slotDataChanged

void KisAnimCurvesView::slotDataChanged ( const QModelIndex & topLeft,
const QModelIndex & bottomRight )
privateslot

Definition at line 804 of file KisAnimCurvesView.cpp.

805{
806 Q_UNUSED(topLeft);
807 Q_UNUSED(bottomRight);
808
809 viewport()->update();
810
811 // this forces the horizontal ruler to refresh. Repaint() doesn't do it for some reason
812 // If you remove this, scrubbing the timeline will probably stop updating the indicator
813 m_d->horizontalHeader->resize(m_d->horizontalHeader->width()-1, m_d->horizontalHeader->height());
814 m_d->horizontalHeader->resize(m_d->horizontalHeader->width()+1, m_d->horizontalHeader->height());
815
816 if (selectionModel()->selection().count() != 0 &&
817 selectionModel()->currentIndex().isValid()) {
818 Q_EMIT activeDataChanged(selectionModel()->currentIndex());
819 }
820}

References activeDataChanged(), and m_d.

◆ slotHeaderDataChanged

void KisAnimCurvesView::slotHeaderDataChanged ( Qt::Orientation orientation,
int first,
int last )
privateslot

Definition at line 840 of file KisAnimCurvesView.cpp.

841{
842 Q_UNUSED(orientation);
843 Q_UNUSED(first);
844 Q_UNUSED(last);
845 viewport()->update();
846}

◆ slotRowsChanged

void KisAnimCurvesView::slotRowsChanged ( const QModelIndex & parentIndex,
int first,
int last )
privateslot

Definition at line 795 of file KisAnimCurvesView.cpp.

796{
797 Q_UNUSED(parentIndex);
798 Q_UNUSED(first);
799 Q_UNUSED(last);
801 viewport()->update();
802}

References zoomToFitChannel().

◆ slotScrollerStateChanged

void KisAnimCurvesView::slotScrollerStateChanged ( QScroller::State state)
inlineslot

Definition at line 63 of file KisAnimCurvesView.h.

KRITAWIDGETUTILS_EXPORT void updateCursor(QWidget *source, QScroller::State state)

References KisKineticScroller::updateCursor().

◆ slotUpdateHorizontalScrollbarSize

void KisAnimCurvesView::slotUpdateHorizontalScrollbarSize ( )
privateslot

Definition at line 856 of file KisAnimCurvesView.cpp.

857{
858 if (m_d->model) {
859 const int lastColumn = qMax( m_d->horizontalHeader->estimateLastVisibleColumn(), m_d->model->columnCount());
860 const int numberOfColumnsOnScreen = lastColumn - m_d->horizontalHeader->estimateFirstVisibleColumn();
861 const int overallSize = lastColumn * m_d->horizontalHeader->defaultSectionSize();
862 const int pageStep = overallSize * (qreal(numberOfColumnsOnScreen) / lastColumn);
863 horizontalScrollBar()->setRange(0, overallSize + pageStep);
864 horizontalScrollBar()->setPageStep(pageStep);
865 }
866}

References m_d.

◆ slotUpdateInfiniteFramesCount

void KisAnimCurvesView::slotUpdateInfiniteFramesCount ( )
privateslot

Definition at line 848 of file KisAnimCurvesView.cpp.

849{
850 if (m_d->model) {
851 const int lastColumn = m_d->horizontalHeader->estimateLastVisibleColumn();
852 m_d->model->setLastVisibleFrame(lastColumn);
853 }
854}

References m_d.

◆ updateGeometries

void KisAnimCurvesView::updateGeometries ( )
overrideprotectedslot

Definition at line 776 of file KisAnimCurvesView.cpp.

777{
778 int topMargin = qMax(m_d->horizontalHeader->minimumHeight(),
779 m_d->horizontalHeader->sizeHint().height());
780
781 int leftMargin = m_d->verticalHeader->sizeHint().width();
782
783 setViewportMargins(leftMargin, topMargin, 0, 0);
784
785 QRect viewRect = viewport()->geometry();
786 m_d->horizontalHeader->setGeometry(leftMargin, 0, viewRect.width(), topMargin);
787 m_d->verticalHeader->setGeometry(0, topMargin, leftMargin, viewRect.height());
788 if (m_d->model) {
790 }
791
792 QAbstractItemView::updateGeometries();
793}

References m_d, and slotUpdateInfiniteFramesCount().

◆ verticalOffset()

int KisAnimCurvesView::verticalOffset ( ) const
overrideprotected

Definition at line 471 of file KisAnimCurvesView.cpp.

472{
473 return m_d->verticalHeader->valueOffset();
474}

References m_d.

◆ visualRect()

QRect KisAnimCurvesView::visualRect ( const QModelIndex & index) const
override

Definition at line 172 of file KisAnimCurvesView.cpp.

173{
174 return m_d->itemDelegate->itemRect(index);
175}

References m_d.

◆ visualRegionForSelection()

QRegion KisAnimCurvesView::visualRegionForSelection ( const QItemSelection & selection) const
overrideprotected

Definition at line 514 of file KisAnimCurvesView.cpp.

515{
516 QRegion region;
517
518 Q_FOREACH(QModelIndex index, selection.indexes()) {
519 region += m_d->itemDelegate->visualRect(index);
520 }
521
522 return region;
523}

References m_d.

◆ zoomToFitChannel

void KisAnimCurvesView::zoomToFitChannel ( )
slot

Definition at line 962 of file KisAnimCurvesView.cpp.

963{
964 if (!model()) return;
965
966 const int channels = model()->rowCount();
967
968 qreal min = 0;
969 qreal max = min;
970
971 for (int channel = 0; channel < channels; channel++) {
972 QModelIndex index = m_d->model->index(channel, 0);
973 QVariant variant = m_d->model->data(index, KisAnimCurvesModel::ChannelLimits);
974
975 if (!variant.isValid())
976 continue;
977
978 ChannelLimitsMetatype limits = variant.value<ChannelLimitsMetatype>();
979 min = qMin(limits.first, min);
980 max = qMax(limits.second, max);
981 }
982
983 if (min == max)
984 {
986 return;
987 }
988
989 const qreal padding = (max - min) * 0.1;
990 m_d->verticalHeader->zoomToFitRange(min - padding, max + padding);
991 viewport()->update();
992}

References KisAnimCurvesModel::ChannelLimits, m_d, and zoomToFitCurve().

◆ zoomToFitCurve

void KisAnimCurvesView::zoomToFitCurve ( )
slot

Definition at line 950 of file KisAnimCurvesView.cpp.

951{
952 if (!model()) return;
953
954 qreal min, max;
955 findExtremes(&min, &max);
956
957 const qreal padding = (min != max) ? (max - min) * 0.1 : 10.0f;
958 m_d->verticalHeader->zoomToFitRange(min - padding, max + padding);
959 viewport()->update();
960}

References findExtremes(), and m_d.

Member Data Documentation

◆ m_d

const QScopedPointer<Private> KisAnimCurvesView::m_d
private

Definition at line 78 of file KisAnimCurvesView.h.


The documentation for this class was generated from the following files: