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

The KisSegmentGradientSlider class makes it possible to edit gradients. More...

#include <KisSegmentGradientSlider.h>

+ Inheritance diagram for KisSegmentGradientSlider:

Classes

struct  Handle
 
struct  TemporallyDeletedHandleInfo
 

Public Types

enum  HandleType { HandleType_None , HandleType_Segment , HandleType_MidPoint , HandleType_Stop }
 

Public Slots

void centerSelectedHandle ()
 
void chooseSelectedStopColor ()
 
void collapseSelectedSegment ()
 
void deleteHandle (Handle handle)
 
void deleteSelectedHandle ()
 
void distributeStopsEvenly ()
 
void duplicateSelectedSegment ()
 
void flipGradient ()
 
void mirrorSelectedSegment ()
 
void moveHandle (Handle handle, qreal distance, bool useShrinkEpsilon=true)
 
void moveHandleLeft (Handle handle, qreal distance, bool useShrinkEpsilon=true)
 
void moveHandleRight (Handle handle, qreal distance, bool useShrinkEpsilon=true)
 
void moveSelectedHandle (qreal distance, bool useShrinkEpsilon=true)
 
void moveSelectedHandleLeft (qreal distance, bool useShrinkEpsilon=true)
 
void moveSelectedHandleRight (qreal distance, bool useShrinkEpsilon=true)
 
void selectNextHandle ()
 
void selectPreviousHandle ()
 
void setGradientResource (KoSegmentGradientSP agr)
 
void splitSelectedSegment ()
 

Signals

void selectedHandleChanged ()
 
void updateRequested ()
 

Public Member Functions

 KisSegmentGradientSlider (QWidget *parent=nullptr, const char *name=nullptr, Qt::WindowFlags f=Qt::WindowFlags())
 
QSize minimumSizeHint () const override
 
Handle selectedHandle ()
 
QSize sizeHint () const override
 

Static Public Attributes

static constexpr qreal shrinkEpsilon = 0.00001
 

Protected Member Functions

void keyPressEvent (QKeyEvent *e) override
 
void leaveEvent (QEvent *e) override
 
void mouseDoubleClickEvent (QMouseEvent *e) override
 
void mouseMoveEvent (QMouseEvent *e) override
 
void mousePressEvent (QMouseEvent *e) override
 
void mouseReleaseEvent (QMouseEvent *e) override
 
void paintEvent (QPaintEvent *) override
 
void wheelEvent (QWheelEvent *e) override
 

Private Slots

void updateHandleSize ()
 

Private Member Functions

bool deleteHandleImpl (Handle handle)
 
QRect gradientStripeRect () const
 
void handleIncrementInput (int direction, Qt::KeyboardModifiers modifiers)
 
QRect handlesStripeRect () const
 
int minimalHeight () const
 
QRect sliderRect () const
 

Private Attributes

bool m_drag {false}
 
qreal m_dragT {0.0}
 
KoSegmentGradientSP m_gradient
 
QSize m_handleSize
 
Handle m_hoveredHandle {HandleType_None, 0}
 
qreal m_relativeDragOffset {0.0}
 
QAction * m_removeSegmentAction {nullptr}
 
QMenu * m_segmentMenu {nullptr}
 
Handle m_selectedHandle {HandleType_None, 0}
 
TemporallyDeletedHandleInfo m_temporallyDeletedHandleInfo
 
KisSignalCompressor m_updateCompressor
 

Static Private Attributes

static constexpr int removeStopDistance {32}
 

Detailed Description

The KisSegmentGradientSlider class makes it possible to edit gradients.

Definition at line 27 of file KisSegmentGradientSlider.h.

Member Enumeration Documentation

◆ HandleType

Enumerator
HandleType_None 
HandleType_Segment 
HandleType_MidPoint 
HandleType_Stop 

Definition at line 32 of file KisSegmentGradientSlider.h.

Constructor & Destructor Documentation

◆ KisSegmentGradientSlider()

KisSegmentGradientSlider::KisSegmentGradientSlider ( QWidget * parent = nullptr,
const char * name = nullptr,
Qt::WindowFlags f = Qt::WindowFlags() )

Definition at line 34 of file KisSegmentGradientSlider.cpp.

35 : QWidget(parent, f)
36 , m_drag(false)
38{
39 setObjectName(name);
40 setMouseTracking(true);
41 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
42 setFocusPolicy(Qt::WheelFocus);
43
44 connect(this, SIGNAL(updateRequested()), &m_updateCompressor, SLOT(start()));
45 connect(&m_updateCompressor, SIGNAL(timeout()), this, SLOT(update()));
46
47 QWindow *window = this->window()->windowHandle();
48 if (window) {
49 connect(window, SIGNAL(screenChanged(QScreen*)), SLOT(updateHandleSize()));
50 }
52}
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
bool update(QSpinBox *spinBox)

References connect(), m_updateCompressor, updateHandleSize(), and updateRequested().

Member Function Documentation

◆ centerSelectedHandle

void KisSegmentGradientSlider::centerSelectedHandle ( )
slot

Definition at line 871 of file KisSegmentGradientSlider.cpp.

872{
874 KoGradientSegment *segment = m_gradient->segments()[m_selectedHandle.index];
875 KoGradientSegment *previousSegment = m_selectedHandle.index == 0 ? nullptr : m_gradient->segments()[m_selectedHandle.index - 1];
876 KoGradientSegment *nextSegment = m_selectedHandle.index == m_gradient->segments().size() - 1 ? nullptr : m_gradient->segments()[m_selectedHandle.index + 1];
877 if (previousSegment && nextSegment) {
879 (previousSegment->startOffset() + nextSegment->endOffset()) / 2.0 -
880 (segment->startOffset() + segment->endOffset()) / 2.0);
881 }
882 } else if (m_selectedHandle.type == HandleType_Stop) {
883 KoGradientSegment *previousSegment = m_selectedHandle.index == 0 ? nullptr : m_gradient->segments()[m_selectedHandle.index - 1];
884 KoGradientSegment *nextSegment = m_selectedHandle.index == m_gradient->segments().size() ? nullptr : m_gradient->segments()[m_selectedHandle.index];
885 if (previousSegment && nextSegment) {
886 moveSelectedHandle((previousSegment->startOffset() + nextSegment->endOffset()) / 2.0 - nextSegment->startOffset());
887 }
889 KoGradientSegment *segment = m_gradient->segments()[m_selectedHandle.index];
890 qDebug() << segment->startOffset() << segment->endOffset() << segment->middleOffset() <<
891 ((segment->startOffset() + segment->endOffset()) / 2);
892 moveSelectedHandle((segment->startOffset() + segment->endOffset()) / 2.0 - segment->middleOffset());
893 }
894}
void moveSelectedHandle(qreal distance, bool useShrinkEpsilon=true)
Write API docs here.

References KoGradientSegment::endOffset(), HandleType_MidPoint, HandleType_Segment, HandleType_Stop, KisSegmentGradientSlider::Handle::index, m_gradient, m_selectedHandle, KoGradientSegment::middleOffset(), moveSelectedHandle(), KoGradientSegment::startOffset(), and KisSegmentGradientSlider::Handle::type.

◆ chooseSelectedStopColor

void KisSegmentGradientSlider::chooseSelectedStopColor ( )
slot

Definition at line 1034 of file KisSegmentGradientSlider.cpp.

1035{
1037 return;
1038 }
1039 QList<KoGradientSegment*> segments = m_gradient->segments();
1040 if (m_selectedHandle.index < 0 || m_selectedHandle.index > segments.size()) {
1041 return;
1042 }
1043
1044 KoColor color1, color2;
1046 if (m_selectedHandle.index == 0) {
1047 endType1 = segments[0]->startType();
1048 color1 = segments[0]->startColor();
1049 } else {
1050 endType1 = segments[m_selectedHandle.index - 1]->endType();
1051 color1 = segments[m_selectedHandle.index - 1]->endColor();
1052 if (m_selectedHandle.index < segments.size()) {
1053 endType2 = segments[m_selectedHandle.index]->startType();
1054 color2 = segments[m_selectedHandle.index]->startColor();
1055 }
1056 }
1057
1058 KConfigGroup cfg = KSharedConfig::openConfig()->group("colorselector");
1059 bool usePlatformDialog = cfg.readEntry("UsePlatformColorDialog", false);
1060 QDialog *colorDialog = nullptr;
1061
1062 if (!usePlatformDialog) {
1064 KisDlgInternalColorSelector *dialog = new KisDlgInternalColorSelector(this, color1, cfg, i18n("Choose a color"));
1065 dialog->setPreviousColor(color1);
1066 auto setColorFn = [dialog, segments, this]() mutable
1067 {
1068 if (m_selectedHandle.index == 0) {
1069 segments[0]->setStartType(COLOR_ENDPOINT);
1070 segments[0]->setStartColor(dialog->getCurrentColor());
1071 } else {
1072 segments[m_selectedHandle.index - 1]->setEndType(COLOR_ENDPOINT);
1073 segments[m_selectedHandle.index - 1]->setEndColor(dialog->getCurrentColor());
1074 if (m_selectedHandle.index < segments.size()) {
1075 segments[m_selectedHandle.index]->setStartType(COLOR_ENDPOINT);
1076 segments[m_selectedHandle.index]->setStartColor(dialog->getCurrentColor());
1077 }
1078 }
1079 Q_EMIT selectedHandleChanged();
1080 Q_EMIT updateRequested();
1081 };
1083 connect(dialog, &QDialog::accepted, setColorFn);
1084 colorDialog = dialog;
1085 } else {
1086 QColorDialog *dialog = new QColorDialog(this);
1087 dialog->setCurrentColor(color1.toQColor());
1088 auto setColorFn = [dialog, segments, this]() mutable
1089 {
1090 KoColor color;
1091 color.fromQColor(dialog->currentColor());
1092 if (m_selectedHandle.index == 0) {
1093 segments[0]->setStartType(COLOR_ENDPOINT);
1094 segments[0]->setStartColor(color);
1095 } else {
1096 segments[m_selectedHandle.index - 1]->setEndType(COLOR_ENDPOINT);
1097 segments[m_selectedHandle.index - 1]->setEndColor(color);
1098 if (m_selectedHandle.index < segments.size()) {
1099 segments[m_selectedHandle.index]->setStartType(COLOR_ENDPOINT);
1100 segments[m_selectedHandle.index]->setStartColor(color);
1101 }
1102 }
1103 Q_EMIT selectedHandleChanged();
1104 Q_EMIT updateRequested();
1105 };
1106 connect(dialog, &QColorDialog::currentColorChanged, setColorFn);
1107 connect(dialog, &QDialog::accepted, setColorFn);
1108 colorDialog = dialog;
1109 }
1110 // common functionality
1111 connect(colorDialog, &QDialog::rejected, [endType1, endType2, color1, color2, segments, this]()
1112 {
1113 if (m_selectedHandle.index == 0) {
1114 segments[0]->setStartType(endType1);
1115 segments[0]->setStartColor(color1);
1116 } else {
1117 segments[m_selectedHandle.index - 1]->setEndType(endType1);
1118 segments[m_selectedHandle.index - 1]->setEndColor(color1);
1119 if (m_selectedHandle.index < segments.size()) {
1120 segments[m_selectedHandle.index]->setStartType(endType2);
1121 segments[m_selectedHandle.index]->setStartColor(color2);
1122 }
1123 }
1124 Q_EMIT selectedHandleChanged();
1125 Q_EMIT updateRequested();
1126 });
1127 colorDialog->setAttribute(Qt::WA_DeleteOnClose);
1128 colorDialog->show();
1129 colorDialog->raise();
1130 colorDialog->activateWindow();
1131}
KoGradientSegmentEndpointType
@ COLOR_ENDPOINT
The KisInternalColorSelector class.
void signalForegroundColorChosen(KoColor color)
signalForegroundColorChosen The most important signal. This will sent out when a color has been chose...
void fromQColor(const QColor &c)
Convenient function for converting from a QColor.
Definition KoColor.cpp:213
void toQColor(QColor *c) const
a convenience method for the above.
Definition KoColor.cpp:198

References COLOR_ENDPOINT, connect(), KoColor::fromQColor(), HandleType_Stop, KisSegmentGradientSlider::Handle::index, m_gradient, m_selectedHandle, selectedHandleChanged(), KisDlgInternalColorSelector::signalForegroundColorChosen(), KoColor::toQColor(), KisSegmentGradientSlider::Handle::type, and updateRequested().

◆ collapseSelectedSegment

void KisSegmentGradientSlider::collapseSelectedSegment ( )
slot

◆ deleteHandle

void KisSegmentGradientSlider::deleteHandle ( Handle handle)
slot

Definition at line 844 of file KisSegmentGradientSlider.cpp.

845{
846 if (deleteHandleImpl(handle)) {
847 Q_EMIT selectedHandleChanged();
848 Q_EMIT updateRequested();
849 }
850}

References deleteHandleImpl(), selectedHandleChanged(), and updateRequested().

◆ deleteHandleImpl()

bool KisSegmentGradientSlider::deleteHandleImpl ( Handle handle)
private

Definition at line 817 of file KisSegmentGradientSlider.cpp.

818{
819 if (handle.type == HandleType_Segment) {
820 if (m_gradient->removeSegment(m_gradient->segments()[handle.index])) {
821 if (m_selectedHandle.index > 0) {
823 }
824 return true;
825 }
826 } else if (m_selectedHandle.type == HandleType_Stop) {
827 if (m_selectedHandle.index <= 0 || m_selectedHandle.index >= m_gradient->segments().size()) {
828 return false;
829 }
830 KoGradientSegment *previousSegment = m_gradient->segments()[m_selectedHandle.index - 1];
831 KoGradientSegment *nextSegment = m_gradient->segments()[m_selectedHandle.index];
832 const qreal middleOffset = previousSegment->endOffset();
833 previousSegment->setEndType(nextSegment->endType());
834 previousSegment->setEndColor(nextSegment->endColor());
835 m_gradient->removeSegment(nextSegment);
836 previousSegment->setMiddleOffset(middleOffset);
839 return true;
840 }
841 return false;
842}
void setEndType(KoGradientSegmentEndpointType type)
void setMiddleOffset(qreal t)
KoGradientSegmentEndpointType endType() const
void setEndColor(const KoColor &color)
const KoColor & endColor() const

References KoGradientSegment::endColor(), KoGradientSegment::endOffset(), KoGradientSegment::endType(), HandleType_Segment, HandleType_Stop, KisSegmentGradientSlider::Handle::index, m_gradient, m_selectedHandle, KoGradientSegment::setEndColor(), KoGradientSegment::setEndType(), KoGradientSegment::setMiddleOffset(), and KisSegmentGradientSlider::Handle::type.

◆ deleteSelectedHandle

void KisSegmentGradientSlider::deleteSelectedHandle ( )
slot

Definition at line 852 of file KisSegmentGradientSlider.cpp.

References deleteHandle(), and m_selectedHandle.

◆ distributeStopsEvenly

void KisSegmentGradientSlider::distributeStopsEvenly ( )
slot

Definition at line 967 of file KisSegmentGradientSlider.cpp.

968{
969 const qreal size = 1.0 / m_gradient->segments().size();
970 for (int i = 0; i < m_gradient->segments().size(); ++i) {
971 KoGradientSegment *segment = m_gradient->segments()[i];
972 const qreal relativeMidPointPosition =
973 (segment->middleOffset() - segment->startOffset()) /
974 (segment->endOffset() - segment->startOffset());
975 segment->setStartOffset(i * size);
976 segment->setEndOffset((i + 1) * size);
977 segment->setMiddleOffset(
978 segment->startOffset() + relativeMidPointPosition *
979 (segment->endOffset() - segment->startOffset()));
980 }
981 Q_EMIT selectedHandleChanged();
982 Q_EMIT updateRequested();
983}
void setStartOffset(qreal t)
int size(const Forest< T > &forest)
Definition KisForest.h:1232

References KoGradientSegment::endOffset(), m_gradient, KoGradientSegment::middleOffset(), selectedHandleChanged(), KoGradientSegment::setEndOffset(), KoGradientSegment::setMiddleOffset(), KoGradientSegment::setStartOffset(), KoGradientSegment::startOffset(), and updateRequested().

◆ duplicateSelectedSegment

void KisSegmentGradientSlider::duplicateSelectedSegment ( )
slot

◆ flipGradient

void KisSegmentGradientSlider::flipGradient ( )
slot

Definition at line 926 of file KisSegmentGradientSlider.cpp.

927{
928 QList<KoGradientSegment*> oldSegments = m_gradient->segments();
929 QList<KoGradientSegment*> newSegments;
930 for (int i = oldSegments.size() - 1; i >= 0; --i) {
931 KoGradientSegment* oldSegment = oldSegments[i];
932 int interpolation = oldSegment->interpolation();
933 int colorInterpolation = oldSegment->colorInterpolation();
934
935 if (interpolation == INTERP_SPHERE_INCREASING) {
936 interpolation = INTERP_SPHERE_DECREASING;
937 }
938 else if (interpolation == INTERP_SPHERE_DECREASING) {
939 interpolation = INTERP_SPHERE_INCREASING;
940 }
941 if (colorInterpolation == COLOR_INTERP_HSV_CW) {
942 colorInterpolation = COLOR_INTERP_HSV_CCW;
943 }
944 else if (colorInterpolation == COLOR_INTERP_HSV_CCW) {
945 colorInterpolation = COLOR_INTERP_HSV_CW;
946 }
947
948 KoGradientSegment* newSegment = new KoGradientSegment(
949 interpolation, colorInterpolation,
950 { 1.0 - oldSegment->endOffset(), oldSegment->endColor(), oldSegment->endType() },
951 { 1.0 - oldSegment->startOffset(), oldSegment->startColor(), oldSegment->startType() },
952 1.0 - oldSegment->middleOffset()
953 );
954
955 newSegments.push_back(newSegment);
956 }
957 m_gradient->setSegments(newSegments);
959 m_selectedHandle.index = newSegments.size() - m_selectedHandle.index;
960 } else {
961 m_selectedHandle.index = newSegments.size() - 1 - m_selectedHandle.index;
962 }
963 Q_EMIT selectedHandleChanged();
964 Q_EMIT updateRequested();
965}
@ INTERP_SPHERE_DECREASING
@ INTERP_SPHERE_INCREASING
@ COLOR_INTERP_HSV_CCW
@ COLOR_INTERP_HSV_CW
KoGradientSegmentEndpointType startType() const
const KoColor & startColor() const

References COLOR_INTERP_HSV_CCW, COLOR_INTERP_HSV_CW, KoGradientSegment::colorInterpolation(), KoGradientSegment::endColor(), KoGradientSegment::endOffset(), KoGradientSegment::endType(), HandleType_Stop, KisSegmentGradientSlider::Handle::index, INTERP_SPHERE_DECREASING, INTERP_SPHERE_INCREASING, KoGradientSegment::interpolation(), m_gradient, m_selectedHandle, KoGradientSegment::middleOffset(), selectedHandleChanged(), KoGradientSegment::startColor(), KoGradientSegment::startOffset(), KoGradientSegment::startType(), KisSegmentGradientSlider::Handle::type, and updateRequested().

◆ gradientStripeRect()

QRect KisSegmentGradientSlider::gradientStripeRect ( ) const
private

Definition at line 992 of file KisSegmentGradientSlider.cpp.

993{
994 const QRect rc = sliderRect();
995 return rc.adjusted(0, 0, 0, -m_handleSize.height() - 4);
996}

References m_handleSize, and sliderRect().

◆ handleIncrementInput()

void KisSegmentGradientSlider::handleIncrementInput ( int direction,
Qt::KeyboardModifiers modifiers )
private

Definition at line 642 of file KisSegmentGradientSlider.cpp.

643{
644 if (direction == 0) {
645 return;
646 }
647 if (modifiers & Qt::ControlModifier) {
648 if (direction < 0) {
650 } else {
652 }
653 } else {
654 const qreal increment = modifiers & Qt::ShiftModifier ? 0.001 : 0.01;
655 moveSelectedHandle(direction < 0 ? -increment : increment);
656 }
657}

References moveSelectedHandle(), selectNextHandle(), and selectPreviousHandle().

◆ handlesStripeRect()

QRect KisSegmentGradientSlider::handlesStripeRect ( ) const
private

Definition at line 998 of file KisSegmentGradientSlider.cpp.

999{
1000 const QRect rc = sliderRect();
1001 return rc.adjusted(0, rc.height() - (m_handleSize.height() + 2), 0, -2);
1002}

References m_handleSize, and sliderRect().

◆ keyPressEvent()

void KisSegmentGradientSlider::keyPressEvent ( QKeyEvent * e)
overrideprotected

Definition at line 669 of file KisSegmentGradientSlider.cpp.

670{
671 switch (e->key()) {
672 case Qt::Key_Left:
673 handleIncrementInput(-1, e->modifiers());
674 break;
675 case Qt::Key_Right:
676 handleIncrementInput(1, e->modifiers());
677 break;
678 case Qt::Key_Return:
679 case Qt::Key_Enter:
681 break;
682 case Qt::Key_Delete:
684 break;
685 default:
686 QWidget::keyPressEvent(e);
687 break;
688 }
689}
void handleIncrementInput(int direction, Qt::KeyboardModifiers modifiers)

References chooseSelectedStopColor(), deleteSelectedHandle(), and handleIncrementInput().

◆ leaveEvent()

void KisSegmentGradientSlider::leaveEvent ( QEvent * e)
overrideprotected

Definition at line 691 of file KisSegmentGradientSlider.cpp.

692{
693 m_hoveredHandle = {};
694 Q_EMIT updateRequested();
695 QWidget::leaveEvent(e);
696}

References m_hoveredHandle, and updateRequested().

◆ minimalHeight()

int KisSegmentGradientSlider::minimalHeight ( ) const
private

Definition at line 1011 of file KisSegmentGradientSlider.cpp.

1012{
1013 QFontMetrics fm(font());
1014 const int h = fm.height();
1015
1016 QStyleOptionToolButton opt;
1017 QSize sz = style()->sizeFromContents(QStyle::CT_ToolButton, &opt, QSize(h, h), this);
1018
1019 return qMax(32, sz.height()) + m_handleSize.height();
1020}

References m_handleSize.

◆ minimumSizeHint()

QSize KisSegmentGradientSlider::minimumSizeHint ( ) const
override

Definition at line 1028 of file KisSegmentGradientSlider.cpp.

1029{
1030 const int h = minimalHeight();
1031 return QSize(h, h);
1032}

References minimalHeight().

◆ mirrorSelectedSegment

void KisSegmentGradientSlider::mirrorSelectedSegment ( )
slot

◆ mouseDoubleClickEvent()

void KisSegmentGradientSlider::mouseDoubleClickEvent ( QMouseEvent * e)
overrideprotected

Definition at line 582 of file KisSegmentGradientSlider.cpp.

583{
584 if (e->button() != Qt::LeftButton) {
585 QWidget::mouseDoubleClickEvent(e);
586 return;
587 }
588
589 const QRect rect = sliderRect();
590 const QRect handlesRect = handlesStripeRect();
591 const qreal t = (e->x() - rect.left()) / static_cast<qreal>(rect.width());
592 const qreal handleClickTolerance = m_handleSize.width() / static_cast<qreal>(rect.width());
593 const KoGradientSegment *previousSegment = m_selectedHandle.index == 0 ? nullptr : m_gradient->segments()[m_selectedHandle.index - 1];
594 const KoGradientSegment *nextSegment = m_selectedHandle.index == m_gradient->segments().size() ? nullptr : m_gradient->segments()[m_selectedHandle.index];
595
596 if ((previousSegment && qAbs(t - previousSegment->endOffset()) <= handleClickTolerance && e->pos().y() >= handlesRect.y()) ||
597 (nextSegment && qAbs(t - nextSegment->startOffset()) <= handleClickTolerance && e->pos().y() >= handlesRect.y())) {
599 }
600}

References chooseSelectedStopColor(), KoGradientSegment::endOffset(), handlesStripeRect(), KisSegmentGradientSlider::Handle::index, m_gradient, m_handleSize, m_selectedHandle, sliderRect(), and KoGradientSegment::startOffset().

◆ mouseMoveEvent()

void KisSegmentGradientSlider::mouseMoveEvent ( QMouseEvent * e)
overrideprotected

Definition at line 351 of file KisSegmentGradientSlider.cpp.

352{
353 const QRect rect = sliderRect();
354 const qreal t = (e->x() - rect.left()) / static_cast<qreal>(rect.width());
355
356 if (m_drag) {
357 if (!(e->buttons() & Qt::LeftButton)) {
358 QWidget::mouseMoveEvent(e);
359 return;
360 }
361 const QRect augmentedRect = kisGrowRect(this->rect(), removeStopDistance);
363 if (augmentedRect.contains(e->pos())) {
364 m_gradient->duplicateSegment(m_gradient->segments()[m_temporallyDeletedHandleInfo.handle.index - 1]);
378 }
380 if (augmentedRect.contains(e->pos())) {
381 m_gradient->duplicateSegment(m_gradient->segments()[m_temporallyDeletedHandleInfo.handle.index - 1]);
382 KoGradientSegment *previousSegment = m_gradient->segments()[m_temporallyDeletedHandleInfo.handle.index - 1];
388 previousSegment->setMiddleOffset(
389 previousSegment->startOffset() +
392 previousSegment->length()
393 );
398 nextSegment->setMiddleOffset(
399 nextSegment->startOffset() +
402 nextSegment->length()
403 );
407 }
408 }
409
412 KoGradientSegment *segment = m_gradient->segments()[m_selectedHandle.index];
413 if (m_gradient->segments().size() > 1 && m_selectedHandle.index > 0 && m_selectedHandle.index < m_gradient->segments().size() - 1 &&
414 !augmentedRect.contains(e->pos())) {
426 m_gradient->collapseSegment(m_gradient->segments()[m_selectedHandle.index]);
428 } else {
429 KoGradientSegment *segment = m_gradient->segments()[m_selectedHandle.index];
430 KoGradientSegment *previousSegment = m_selectedHandle.index == 0 ? nullptr : m_gradient->segments()[m_selectedHandle.index - 1];
431 KoGradientSegment *nextSegment = m_selectedHandle.index == m_gradient->segments().size() - 1 ? nullptr : m_gradient->segments()[m_selectedHandle.index + 1];
432 if (previousSegment && nextSegment) {
433 const qreal midPointRelativePos = segment->middleOffset() - segment->startOffset();
434 const qreal previousMidPointLocalPos =
435 previousSegment->length() > std::numeric_limits<qreal>::epsilon()
436 ? (previousSegment->middleOffset() - previousSegment->startOffset()) / previousSegment->length()
437 : 0.0;
438 const qreal nextMidPointLocalPos =
439 nextSegment->length() > std::numeric_limits<qreal>::epsilon()
440 ? (nextSegment->middleOffset() - nextSegment->startOffset()) / nextSegment->length()
441 : 0.0;
442 qreal newStartOffset, newEndOffset;
443 if (t < m_dragT) {
444 newStartOffset = qMax(t - m_relativeDragOffset, previousSegment->startOffset() + shrinkEpsilon);
445 newEndOffset = newStartOffset + segment->length();
446 } else {
447 newEndOffset = qMin(t + (segment->length() - m_relativeDragOffset), nextSegment->endOffset() - shrinkEpsilon);
448 newStartOffset = newEndOffset - segment->length();
449 }
450 previousSegment->setEndOffset(newStartOffset);
451 segment->setStartOffset(newStartOffset);
452 segment->setEndOffset(newEndOffset);
453 nextSegment->setStartOffset(newEndOffset);
454 previousSegment->setMiddleOffset(
455 previousSegment->startOffset() +
456 previousMidPointLocalPos * previousSegment->length()
457 );
458 nextSegment->setMiddleOffset(
459 nextSegment->startOffset() +
460 nextMidPointLocalPos * nextSegment->length()
461 );
462 segment->setMiddleOffset(segment->startOffset() + midPointRelativePos);
463 } else {
464 if (!previousSegment) {
465 segment->setStartOffset(0.0);
466 }
467 if (!nextSegment) {
468 segment->setEndOffset(1.0);
469 }
470 }
471 }
472 Q_EMIT selectedHandleChanged();
473 Q_EMIT updateRequested();
474 }
475
476 } else if (m_selectedHandle.type == HandleType_Stop) {
478 KoGradientSegment *previousSegment = m_selectedHandle.index == 0 ? nullptr : m_gradient->segments()[m_selectedHandle.index - 1];
479 KoGradientSegment *nextSegment = m_selectedHandle.index == m_gradient->segments().size() ? nullptr : m_gradient->segments()[m_selectedHandle.index];
480 if (m_gradient->segments().size() > 1 && m_selectedHandle.index > 0 && m_selectedHandle.index < m_gradient->segments().size() &&
481 !augmentedRect.contains(e->pos())) {
496 previousSegment->setEndType(nextSegment->endType());
497 previousSegment->setEndColor(nextSegment->endColor());
500 } else {
501 KoGradientSegment *previousSegment = m_selectedHandle.index == 0 ? nullptr : m_gradient->segments()[m_selectedHandle.index - 1];
502 KoGradientSegment *nextSegment = m_selectedHandle.index == m_gradient->segments().size() ? nullptr : m_gradient->segments()[m_selectedHandle.index];
503 if (previousSegment && nextSegment) {
504 const qreal previousMidPointLocalPos =
505 previousSegment->length() > std::numeric_limits<qreal>::epsilon()
506 ? (previousSegment->middleOffset() - previousSegment->startOffset()) / previousSegment->length()
507 : 0.0;
508 const qreal nextMidPointLocalPos =
509 nextSegment->length() > std::numeric_limits<qreal>::epsilon()
510 ? (nextSegment->middleOffset() - nextSegment->startOffset()) / nextSegment->length()
511 : 0.0;
512 qreal newOffset;
513 if (t < m_dragT) {
514 newOffset = qMax(t, previousSegment->startOffset() + shrinkEpsilon);
515 } else {
516 newOffset = qMin(t, nextSegment->endOffset() - shrinkEpsilon);
517 }
518 previousSegment->setEndOffset(newOffset);
519 nextSegment->setStartOffset(newOffset);
520 previousSegment->setMiddleOffset(
521 previousSegment->startOffset() +
522 previousMidPointLocalPos * previousSegment->length()
523 );
524 nextSegment->setMiddleOffset(
525 nextSegment->startOffset() +
526 nextMidPointLocalPos * nextSegment->length()
527 );
528 } else {
529 if (!previousSegment) {
530 nextSegment->setStartOffset(0.0);
531 }
532 if (!nextSegment) {
533 previousSegment->setEndOffset(1.0);
534 }
535 }
536 }
537 Q_EMIT selectedHandleChanged();
538 Q_EMIT updateRequested();
539 }
540
542 KoGradientSegment *segment = m_gradient->segments()[m_selectedHandle.index];
543 segment->setMiddleOffset(qBound(segment->startOffset(), t, segment->endOffset()));
544 Q_EMIT selectedHandleChanged();
545 Q_EMIT updateRequested();
546 }
547
548 } else {
549 const QRect handlesRect = handlesStripeRect();
550 Handle hoveredHandle;
551 const qreal handleClickTolerance = m_handleSize.width() / static_cast<qreal>(rect.width());
552 for (int i = 0; i < m_gradient->segments().size(); ++i) {
553 KoGradientSegment *segment = m_gradient->segments()[i];
554 // Check if a knob was hovered
555 if (qAbs(t - segment->startOffset()) <= handleClickTolerance && e->pos().y() >= handlesRect.y()) {
556 // Left knob was hovered
557 hoveredHandle.type = HandleType_Stop;
558 hoveredHandle.index = i;
559 break;
560 } else if (qAbs(t - segment->endOffset()) <= handleClickTolerance && e->pos().y() >= handlesRect.y()) {
561 // Right knob was hovered
562 hoveredHandle.type = HandleType_Stop;
563 hoveredHandle.index = i + 1;
564 break;
565 } else if (qAbs(t - segment->middleOffset()) <= handleClickTolerance && e->pos().y() >= handlesRect.y()) {
566 // middle knob was hovered
567 hoveredHandle.type = HandleType_MidPoint;
568 hoveredHandle.index = i;
569 break;
570 } else if (t >= segment->startOffset() && t <= segment->endOffset()) {
571 // the segment area was hovered
572 hoveredHandle.type = HandleType_Segment;
573 hoveredHandle.index = i;
574 break;
575 }
576 }
577 m_hoveredHandle = hoveredHandle;
578 Q_EMIT updateRequested();
579 }
580}
static constexpr int removeStopDistance
static constexpr qreal shrinkEpsilon
TemporallyDeletedHandleInfo m_temporallyDeletedHandleInfo
void setInterpolation(int interpolationType)
void setColorInterpolation(int colorInterpolationType)
void setStartColor(const KoColor &color)
void setStartType(KoGradientSegmentEndpointType type)
T kisGrowRect(const T &rect, U offset)
Definition kis_global.h:186

References KoGradientSegment::colorInterpolation(), deleteHandleImpl(), KoGradientSegment::endColor(), KoGradientSegment::endOffset(), KoGradientSegment::endType(), KisSegmentGradientSlider::TemporallyDeletedHandleInfo::handle, handlesStripeRect(), HandleType_MidPoint, HandleType_None, HandleType_Segment, HandleType_Stop, KisSegmentGradientSlider::Handle::index, KoGradientSegment::interpolation(), kisGrowRect(), KisSegmentGradientSlider::TemporallyDeletedHandleInfo::leftColorInterpolationType, KisSegmentGradientSlider::TemporallyDeletedHandleInfo::leftEndPointColor, KisSegmentGradientSlider::TemporallyDeletedHandleInfo::leftEndPointOffset, KisSegmentGradientSlider::TemporallyDeletedHandleInfo::leftEndPointType, KisSegmentGradientSlider::TemporallyDeletedHandleInfo::leftInterpolationType, KisSegmentGradientSlider::TemporallyDeletedHandleInfo::leftMiddleOffset, KoGradientSegment::length(), m_drag, m_dragT, m_gradient, m_handleSize, m_hoveredHandle, m_relativeDragOffset, m_selectedHandle, m_temporallyDeletedHandleInfo, KoGradientSegment::middleOffset(), removeStopDistance, KisSegmentGradientSlider::TemporallyDeletedHandleInfo::rightColorInterpolationType, KisSegmentGradientSlider::TemporallyDeletedHandleInfo::rightEndPointColor, KisSegmentGradientSlider::TemporallyDeletedHandleInfo::rightEndPointOffset, KisSegmentGradientSlider::TemporallyDeletedHandleInfo::rightEndPointType, KisSegmentGradientSlider::TemporallyDeletedHandleInfo::rightInterpolationType, KisSegmentGradientSlider::TemporallyDeletedHandleInfo::rightMiddleOffset, selectedHandleChanged(), KoGradientSegment::setColorInterpolation(), KoGradientSegment::setEndColor(), KoGradientSegment::setEndOffset(), KoGradientSegment::setEndType(), KoGradientSegment::setInterpolation(), KoGradientSegment::setMiddleOffset(), KoGradientSegment::setStartColor(), KoGradientSegment::setStartOffset(), KoGradientSegment::setStartType(), shrinkEpsilon, sliderRect(), KoGradientSegment::startColor(), KoGradientSegment::startOffset(), KoGradientSegment::startType(), KisSegmentGradientSlider::Handle::type, and updateRequested().

◆ mousePressEvent()

void KisSegmentGradientSlider::mousePressEvent ( QMouseEvent * e)
overrideprotected

Definition at line 267 of file KisSegmentGradientSlider.cpp.

268{
269 if (e->button() != Qt::LeftButton) {
270 QWidget::mousePressEvent(e);
271 return;
272 }
273
274 const QRect rect = sliderRect();
275 const QRect handlesRect = handlesStripeRect();
276
277 // Find segment under cursor
278 Handle selectedHandle;
279 const qreal t = (e->x() - rect.left()) / static_cast<qreal>(rect.width());
280 const qreal handleClickTolerance = m_handleSize.width() / static_cast<qreal>(rect.width());
281 m_dragT = t;
282
283 for (int i = 0; i < m_gradient->segments().size(); ++i) {
284 KoGradientSegment *segment = m_gradient->segments()[i];
285 // Check if a knob was pressed
286 if (qAbs(t - segment->startOffset()) <= handleClickTolerance && e->pos().y() >= handlesRect.y()) {
287 // Left knob was pressed
290 m_drag = true;
291 break;
292 } else if (qAbs(t - segment->endOffset()) <= handleClickTolerance && e->pos().y() >= handlesRect.y()) {
293 // Right knob was pressed
295 selectedHandle.index = i + 1;
296 m_drag = true;
297 break;
298 } else if (qAbs(t - segment->middleOffset()) <= handleClickTolerance && e->pos().y() >= handlesRect.y()) {
299 // middle knob was pressed
302 m_drag = true;
303 break;
304 } else if (t >= segment->startOffset() && t <= segment->endOffset()) {
305 // the segment area was pressed
308 if (e->modifiers() & Qt::ControlModifier) {
309 KoColor color;
310 m_gradient->colorAt(color, t);
312 segment->setMiddleOffset(t);
313 m_gradient->splitSegment(segment);
315 m_selectedHandle.index = i + 1;
316 m_gradient->segments()[i]->setEndColor(color);
317 m_gradient->segments()[i + 1]->setStartColor(color);
318 m_drag = true;
319 Q_EMIT selectedHandleChanged();
320 Q_EMIT updateRequested();
321 return;
322 } else if (e->modifiers() & Qt::ShiftModifier) {
325 return;
326 }
327 m_drag = true;
328 m_relativeDragOffset = t - segment->startOffset();
329 break;
330 }
331 }
332
333 if (m_drag) {
334 m_hoveredHandle = {};
335 }
336
339 Q_EMIT selectedHandleChanged();
340 Q_EMIT updateRequested();
341 }
342}

References duplicateSelectedSegment(), KoGradientSegment::endOffset(), handlesStripeRect(), HandleType_MidPoint, HandleType_Segment, HandleType_Stop, KisSegmentGradientSlider::Handle::index, m_drag, m_dragT, m_gradient, m_handleSize, m_hoveredHandle, m_relativeDragOffset, m_selectedHandle, KoGradientSegment::middleOffset(), selectedHandle(), selectedHandleChanged(), KoGradientSegment::setMiddleOffset(), sliderRect(), KoGradientSegment::startOffset(), KisSegmentGradientSlider::Handle::type, and updateRequested().

◆ mouseReleaseEvent()

void KisSegmentGradientSlider::mouseReleaseEvent ( QMouseEvent * e)
overrideprotected

◆ moveHandle

void KisSegmentGradientSlider::moveHandle ( Handle handle,
qreal distance,
bool useShrinkEpsilon = true )
slot

Definition at line 698 of file KisSegmentGradientSlider.cpp.

699{
700 const qreal epsilon = useShrinkEpsilon ? shrinkEpsilon : 0.0;
701 if (handle.type == HandleType_Segment) {
702 KoGradientSegment *segment = m_gradient->segments()[handle.index];
703 KoGradientSegment *previousSegment = handle.index == 0 ? nullptr : m_gradient->segments()[handle.index - 1];
704 KoGradientSegment *nextSegment = handle.index == m_gradient->segments().size() - 1 ? nullptr : m_gradient->segments()[handle.index + 1];
705 if (previousSegment && nextSegment) {
706 const qreal midPointRelativePos = segment->middleOffset() - segment->startOffset();
707 const qreal previousMidPointLocalPos =
708 previousSegment->length() > std::numeric_limits<qreal>::epsilon()
709 ? (previousSegment->middleOffset() - previousSegment->startOffset()) / previousSegment->length()
710 : 0.0;
711 const qreal nextMidPointLocalPos =
712 nextSegment->length() > std::numeric_limits<qreal>::epsilon()
713 ? (nextSegment->middleOffset() - nextSegment->startOffset()) / nextSegment->length()
714 : 0.0;
715 qreal newStartOffset, newEndOffset;
716 if (distance < 0.0) {
717 newStartOffset = qMax(segment->startOffset() + distance, previousSegment->startOffset() + epsilon);
718 newEndOffset = newStartOffset + segment->length();
719 } else {
720 newEndOffset = qMin(segment->endOffset() + distance, nextSegment->endOffset() - epsilon);
721 newStartOffset = newEndOffset - segment->length();
722 }
723 previousSegment->setEndOffset(newStartOffset);
724 segment->setStartOffset(newStartOffset);
725 segment->setEndOffset(newEndOffset);
726 nextSegment->setStartOffset(newEndOffset);
727 previousSegment->setMiddleOffset(
728 previousSegment->startOffset() +
729 previousMidPointLocalPos * previousSegment->length()
730 );
731 nextSegment->setMiddleOffset(
732 nextSegment->startOffset() +
733 nextMidPointLocalPos * nextSegment->length()
734 );
735 segment->setMiddleOffset(segment->startOffset() + midPointRelativePos);
736 } else {
737 if (!previousSegment) {
738 segment->setStartOffset(0.0);
739 }
740 if (!nextSegment) {
741 segment->setEndOffset(1.0);
742 }
743 }
744 Q_EMIT selectedHandleChanged();
745 Q_EMIT updateRequested();
746 } else if (handle.type == HandleType_Stop) {
747 KoGradientSegment *previousSegment = handle.index == 0 ? nullptr : m_gradient->segments()[handle.index - 1];
748 KoGradientSegment *nextSegment = handle.index == m_gradient->segments().size() ? nullptr : m_gradient->segments()[handle.index];
749 if (previousSegment && nextSegment) {
750 const qreal previousMidPointLocalPos =
751 previousSegment->length() > std::numeric_limits<qreal>::epsilon()
752 ? (previousSegment->middleOffset() - previousSegment->startOffset()) / previousSegment->length()
753 : 0.0;
754 const qreal nextMidPointLocalPos =
755 nextSegment->length() > std::numeric_limits<qreal>::epsilon()
756 ? (nextSegment->middleOffset() - nextSegment->startOffset()) / nextSegment->length()
757 : 0.0;
758 qreal newOffset;
759 if (distance < 0) {
760 newOffset = qMax(previousSegment->endOffset() + distance, previousSegment->startOffset() + epsilon);
761 } else {
762 newOffset = qMin(previousSegment->endOffset() + distance, nextSegment->endOffset() - epsilon);
763 }
764 previousSegment->setEndOffset(newOffset);
765 nextSegment->setStartOffset(newOffset);
766 previousSegment->setMiddleOffset(
767 previousSegment->startOffset() +
768 previousMidPointLocalPos * previousSegment->length()
769 );
770 nextSegment->setMiddleOffset(
771 nextSegment->startOffset() +
772 nextMidPointLocalPos * nextSegment->length()
773 );
774 } else {
775 if (!previousSegment) {
776 nextSegment->setStartOffset(0.0);
777 }
778 if (!nextSegment) {
779 previousSegment->setEndOffset(1.0);
780 }
781 }
782 Q_EMIT selectedHandleChanged();
783 Q_EMIT updateRequested();
784 } else if (handle.type == HandleType_MidPoint) {
785 KoGradientSegment *segment = m_gradient->segments()[handle.index];
786 segment->setMiddleOffset(qBound(segment->startOffset(), segment->middleOffset() + distance, segment->endOffset()));
787 Q_EMIT selectedHandleChanged();
788 Q_EMIT updateRequested();
789 }
790}
qreal distance(const QPointF &p1, const QPointF &p2)

References distance(), KoGradientSegment::endOffset(), HandleType_MidPoint, HandleType_Segment, HandleType_Stop, KisSegmentGradientSlider::Handle::index, KoGradientSegment::length(), m_gradient, KoGradientSegment::middleOffset(), selectedHandleChanged(), KoGradientSegment::setEndOffset(), KoGradientSegment::setMiddleOffset(), KoGradientSegment::setStartOffset(), shrinkEpsilon, KoGradientSegment::startOffset(), KisSegmentGradientSlider::Handle::type, and updateRequested().

◆ moveHandleLeft

void KisSegmentGradientSlider::moveHandleLeft ( Handle handle,
qreal distance,
bool useShrinkEpsilon = true )
slot

Definition at line 792 of file KisSegmentGradientSlider.cpp.

793{
794 moveHandle(handle, -distance, useShrinkEpsilon);
795}
void moveHandle(Handle handle, qreal distance, bool useShrinkEpsilon=true)

References distance(), and moveHandle().

◆ moveHandleRight

void KisSegmentGradientSlider::moveHandleRight ( Handle handle,
qreal distance,
bool useShrinkEpsilon = true )
slot

Definition at line 797 of file KisSegmentGradientSlider.cpp.

798{
799 moveHandle(handle, distance, useShrinkEpsilon);
800}

References distance(), and moveHandle().

◆ moveSelectedHandle

void KisSegmentGradientSlider::moveSelectedHandle ( qreal distance,
bool useShrinkEpsilon = true )
slot

Definition at line 802 of file KisSegmentGradientSlider.cpp.

803{
804 moveHandle(m_selectedHandle, distance, useShrinkEpsilon);
805}

References distance(), m_selectedHandle, and moveHandle().

◆ moveSelectedHandleLeft

void KisSegmentGradientSlider::moveSelectedHandleLeft ( qreal distance,
bool useShrinkEpsilon = true )
slot

Definition at line 807 of file KisSegmentGradientSlider.cpp.

808{
809 moveSelectedHandle(-distance, useShrinkEpsilon);
810}

References distance(), and moveSelectedHandle().

◆ moveSelectedHandleRight

void KisSegmentGradientSlider::moveSelectedHandleRight ( qreal distance,
bool useShrinkEpsilon = true )
slot

Definition at line 812 of file KisSegmentGradientSlider.cpp.

813{
814 moveSelectedHandle(distance, useShrinkEpsilon);
815}

References distance(), and moveSelectedHandle().

◆ paintEvent()

void KisSegmentGradientSlider::paintEvent ( QPaintEvent * )
overrideprotected

Definition at line 62 of file KisSegmentGradientSlider.cpp.

63{
64 QPainter painter(this);
65
66 const QRect previewRect = gradientStripeRect();
67
68 if (m_gradient) {
69 // Gradient
71 // Handles
72 QList<KoGradientSegment*> segments = m_gradient->segments();
73 painter.setRenderHint(QPainter::Antialiasing, true);
74 const QRect handlesRect = this->handlesStripeRect();
75 const bool hasFocus = this->hasFocus();
76 // Segment handles
78 const KoGradientSegment *selectedSegment = segments[m_selectedHandle.index];
79 QRectF segmentHandleRect =
80 handlesRect.adjusted(
81 selectedSegment->startOffset() * handlesRect.width(),
82 -1,
83 -(handlesRect.width() - selectedSegment->endOffset() * handlesRect.width()),
84 -4
85 );
86 painter.fillRect(segmentHandleRect, palette().highlight());
87 }
90 const KoGradientSegment *hoveredSegment = segments[m_hoveredHandle.index];
91 QRectF segmentHandleRect =
92 handlesRect.adjusted(
93 hoveredSegment->startOffset() * handlesRect.width(),
94 -1,
95 -(handlesRect.width() - hoveredSegment->endOffset() * handlesRect.width()),
96 -4
97 );
98 QColor c = palette().highlight().color();
99 c.setAlpha(96);
100 painter.fillRect(segmentHandleRect, c);
101 }
102 // Mid-Point handles
103 const qreal midPointHandleSize = m_handleSize.height() * 0.5;
104 const qreal midPointHandleOffsetY = (handlesRect.height() - 5.0 - midPointHandleSize) * 0.5;
105 for (int i = 0; i < segments.count(); i++) {
107 // If this handle is selected then we will paint it later
108 // on top of everything else
109 continue;
110 }
111 QPointF handlePos =
112 handlesRect.topLeft() +
113 QPointF(segments[i]->middleOffset() * handlesRect.width(), midPointHandleOffsetY);
115 painter, handlePos, midPointHandleSize,
117 palette().windowText().color(), palette().window().color(), palette().highlight().color()
118 );
119 }
120 // Stop handles
121 const QColor highlightColor = palette().color(QPalette::Highlight);
122 // First stop if it is not selected, in which case it will be painted
123 // later on top of everything else
125 KoGradientSegment* segment = segments.front();
127 // Pass the color info as color 2 so that the type indicator is
128 // shown on the right side of the handle for this stop
130 painter,
131 QPointF(handlesRect.left() + segment->startOffset() * handlesRect.width(), handlesRect.top()),
132 QSizeF(m_handleSize),
133 false, m_hoveredHandle.type == HandleType_Stop && m_hoveredHandle.index == 0, hasFocus,
134 highlightColor,
135 {},
136 { colorType, segment->startColor().toQColor() }
137 );
138 }
139 // Middle stops
140 if (segments.size() > 1) {
141 for (int i = 0; i < segments.count() - 1; ++i) {
143 // If this handle is selected then we will paint it later
144 // on top of everything else
145 continue;
146 }
147 KoGradientSegment* currentSegment = segments[i];
148 KoGradientSegment* nextSegment = segments[i + 1];
149 // If the end point of the current segment and the start point
150 // of the next segment have the same offset, that means the
151 // segments touch each other, are connected (normal behavior),
152 // so we paint a single special handle.
153 // If the end points have different offsets then krita stills
154 // considers the gradient valid (although Gimp doesn't) so we
155 // paint two different handles.
156 if (currentSegment->endOffset() == nextSegment->startOffset()) {
158 painter,
159 QPointF(handlesRect.left() + currentSegment->endOffset() * handlesRect.width(), handlesRect.top()),
160 QSizeF(m_handleSize),
161 false, m_hoveredHandle.type == HandleType_Stop && m_hoveredHandle.index == i + 1, hasFocus,
162 highlightColor,
163 { KisGradientWidgetsUtils::segmentEndPointTypeToColorType(currentSegment->endType()), currentSegment->endColor().toQColor() },
164 { KisGradientWidgetsUtils::segmentEndPointTypeToColorType(nextSegment->startType()), nextSegment->startColor().toQColor() }
165 );
166 } else {
168 painter,
169 QPointF(handlesRect.left() + currentSegment->endOffset() * handlesRect.width(), handlesRect.top()),
170 QSizeF(m_handleSize),
171 false, m_hoveredHandle.type == HandleType_Stop && m_hoveredHandle.index == i + 1, hasFocus,
172 highlightColor,
173 { KisGradientWidgetsUtils::segmentEndPointTypeToColorType(currentSegment->endType()), currentSegment->endColor().toQColor() }
174 );
176 painter,
177 QPointF(handlesRect.left() + nextSegment->startOffset() * handlesRect.width(), handlesRect.top()),
178 QSizeF(m_handleSize),
179 false, m_hoveredHandle.type == HandleType_Stop && m_hoveredHandle.index == i + 1, hasFocus,
180 highlightColor,
181 { KisGradientWidgetsUtils::segmentEndPointTypeToColorType(nextSegment->startType()), nextSegment->startColor().toQColor() }
182 );
183 }
184 }
185 }
186 // Last stop. This is the last thing to be painted before the selected
187 // handle, so we don't need to make a special case here
188 {
189 KoGradientSegment* segment = segments.back();
192 painter,
193 QPointF(handlesRect.left() + segment->endOffset() * handlesRect.width(), handlesRect.top()),
194 QSizeF(m_handleSize),
196 m_hoveredHandle.type == HandleType_Stop && m_hoveredHandle.index == segments.size() &&
198 hasFocus,
199 highlightColor,
200 { colorType, segment->endColor().toQColor() }
201 );
202 }
203 // Selected stop
205 QPointF handlePos =
206 handlesRect.topLeft() +
207 QPointF(segments[m_selectedHandle.index]->middleOffset() * handlesRect.width(), midPointHandleOffsetY);
209 painter, handlePos, midPointHandleSize,
210 true, false, hasFocus,
211 palette().windowText().color(), palette().window().color(), palette().highlight().color()
212 );
213 } else if (m_selectedHandle.type == HandleType_Stop) {
214 if (m_selectedHandle.index == 0) {
215 KoGradientSegment* segment = segments.front();
217 // Pass the color info as color 2 so that the type indicator is
218 // shown on the right side of the handle for this stop
220 painter,
221 QPointF(handlesRect.left() + segment->startOffset() * handlesRect.width(), handlesRect.top()),
222 QSizeF(m_handleSize),
223 true, false, hasFocus,
224 highlightColor,
225 {},
226 { colorType, segment->startColor().toQColor() }
227 );
228 } else if (m_selectedHandle.index < segments.size()) {
229 KoGradientSegment* currentSegment = segments[m_selectedHandle.index - 1];
230 KoGradientSegment* nextSegment = segments[m_selectedHandle.index];
231 if (currentSegment->endOffset() == nextSegment->startOffset()) {
233 painter,
234 QPointF(handlesRect.left() + currentSegment->endOffset() * handlesRect.width(), handlesRect.top()),
235 QSizeF(m_handleSize),
236 true, false, hasFocus,
237 highlightColor,
238 { KisGradientWidgetsUtils::segmentEndPointTypeToColorType(currentSegment->endType()), currentSegment->endColor().toQColor() },
240 );
241 } else {
243 painter,
244 QPointF(handlesRect.left() + currentSegment->endOffset() * handlesRect.width(), handlesRect.top()),
245 QSizeF(m_handleSize),
246 true, false, hasFocus,
247 highlightColor,
248 { KisGradientWidgetsUtils::segmentEndPointTypeToColorType(currentSegment->endType()), currentSegment->endColor().toQColor() }
249 );
251 painter,
252 QPointF(handlesRect.left() + nextSegment->startOffset() * handlesRect.width(), handlesRect.top()),
253 QSizeF(m_handleSize),
254 true, false, hasFocus,
255 highlightColor,
257 );
258 }
259 }
260 }
261 } else {
262 painter.setPen(palette().color(QPalette::Mid));
263 painter.drawRect(previewRect);
264 }
265}
void paintGradientBox(QPainter &painter, const KoAbstractGradientSP gradient, const QRectF &rect)
void paintStopHandle(QPainter &painter, const QPointF &position, const QSizeF &size, bool isSelected, bool isHovered, bool hasFocus, const QColor &highlightColor, const StopHandleColor &color1, const StopHandleColor &color2)
KisGradientWidgetsUtils::ColorType segmentEndPointTypeToColorType(KoGradientSegmentEndpointType type)
void paintMidPointHandle(QPainter &painter, const QPointF &position, qreal size, bool isSelected, bool isHovered, bool hasFocus, const QColor &borderColor, const QColor &fillColor, const QColor &highlightColor)
rgba palette[MAX_PALETTE]
Definition palette.c:35

References KoGradientSegment::endColor(), KoGradientSegment::endOffset(), KoGradientSegment::endType(), gradientStripeRect(), handlesStripeRect(), HandleType_MidPoint, HandleType_Segment, HandleType_Stop, KisSegmentGradientSlider::Handle::index, m_gradient, m_handleSize, m_hoveredHandle, m_selectedHandle, KisGradientWidgetsUtils::paintGradientBox(), KisGradientWidgetsUtils::paintMidPointHandle(), KisGradientWidgetsUtils::paintStopHandle(), palette, KisGradientWidgetsUtils::segmentEndPointTypeToColorType(), KoGradientSegment::startColor(), KoGradientSegment::startOffset(), KoGradientSegment::startType(), KoColor::toQColor(), and KisSegmentGradientSlider::Handle::type.

◆ selectedHandle()

Handle KisSegmentGradientSlider::selectedHandle ( )
inline

Definition at line 50 of file KisSegmentGradientSlider.h.

50{ return m_selectedHandle; }

◆ selectedHandleChanged

void KisSegmentGradientSlider::selectedHandleChanged ( )
signal

◆ selectNextHandle

◆ selectPreviousHandle

◆ setGradientResource

void KisSegmentGradientSlider::setGradientResource ( KoSegmentGradientSP agr)
slot

◆ sizeHint()

QSize KisSegmentGradientSlider::sizeHint ( ) const
override

Definition at line 1022 of file KisSegmentGradientSlider.cpp.

1023{
1024 const int h = minimalHeight();
1025 return QSize(2 * h, h);
1026}

References minimalHeight().

◆ sliderRect()

QRect KisSegmentGradientSlider::sliderRect ( ) const
private

Definition at line 985 of file KisSegmentGradientSlider.cpp.

986{
987 const qreal handleWidthOverTwo = static_cast<qreal>(m_handleSize.width()) / 2.0;
988 const int hMargin = static_cast<int>(std::ceil(handleWidthOverTwo)) + 2;
989 return rect().adjusted(hMargin, 0, -hMargin, 0);
990}

References m_handleSize.

◆ splitSelectedSegment

void KisSegmentGradientSlider::splitSelectedSegment ( )
slot

◆ updateHandleSize

void KisSegmentGradientSlider::updateHandleSize ( )
privateslot

Definition at line 1004 of file KisSegmentGradientSlider.cpp.

1005{
1006 QFontMetrics fm(font());
1007 const int h = qMax(15, static_cast<int>(std::ceil(fm.height() * 0.75)));
1008 m_handleSize = QSize(h * 0.75, h);
1009}

References m_handleSize.

◆ updateRequested

void KisSegmentGradientSlider::updateRequested ( )
signal

◆ wheelEvent()

void KisSegmentGradientSlider::wheelEvent ( QWheelEvent * e)
overrideprotected

Definition at line 659 of file KisSegmentGradientSlider.cpp.

660{
661 if (e->angleDelta().y() != 0) {
662 handleIncrementInput(e->angleDelta().y(), e->modifiers());
663 e->accept();
664 } else {
665 QWidget::wheelEvent(e);
666 }
667}

References handleIncrementInput().

Member Data Documentation

◆ m_drag

bool KisSegmentGradientSlider::m_drag {false}
private

Definition at line 117 of file KisSegmentGradientSlider.h.

117{false};

◆ m_dragT

qreal KisSegmentGradientSlider::m_dragT {0.0}
private

Definition at line 118 of file KisSegmentGradientSlider.h.

118{0.0};

◆ m_gradient

KoSegmentGradientSP KisSegmentGradientSlider::m_gradient
private

Definition at line 113 of file KisSegmentGradientSlider.h.

◆ m_handleSize

QSize KisSegmentGradientSlider::m_handleSize
private

Definition at line 121 of file KisSegmentGradientSlider.h.

◆ m_hoveredHandle

Handle KisSegmentGradientSlider::m_hoveredHandle {HandleType_None, 0}
private

Definition at line 115 of file KisSegmentGradientSlider.h.

115{HandleType_None, 0};

◆ m_relativeDragOffset

qreal KisSegmentGradientSlider::m_relativeDragOffset {0.0}
private

Definition at line 119 of file KisSegmentGradientSlider.h.

119{0.0};

◆ m_removeSegmentAction

QAction* KisSegmentGradientSlider::m_removeSegmentAction {nullptr}
private

Definition at line 120 of file KisSegmentGradientSlider.h.

120{nullptr};

◆ m_segmentMenu

QMenu* KisSegmentGradientSlider::m_segmentMenu {nullptr}
private

Definition at line 116 of file KisSegmentGradientSlider.h.

116{nullptr};

◆ m_selectedHandle

Handle KisSegmentGradientSlider::m_selectedHandle {HandleType_None, 0}
private

Definition at line 114 of file KisSegmentGradientSlider.h.

114{HandleType_None, 0};

◆ m_temporallyDeletedHandleInfo

TemporallyDeletedHandleInfo KisSegmentGradientSlider::m_temporallyDeletedHandleInfo
private

Definition at line 122 of file KisSegmentGradientSlider.h.

◆ m_updateCompressor

KisSignalCompressor KisSegmentGradientSlider::m_updateCompressor
private

Definition at line 123 of file KisSegmentGradientSlider.h.

◆ removeStopDistance

constexpr int KisSegmentGradientSlider::removeStopDistance {32}
staticconstexprprivate

Definition at line 112 of file KisSegmentGradientSlider.h.

112{32};

◆ shrinkEpsilon

constexpr qreal KisSegmentGradientSlider::shrinkEpsilon = 0.00001
staticconstexpr

Definition at line 46 of file KisSegmentGradientSlider.h.


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