10#include <QContextMenuEvent>
15#include <QStyleOptionToolButton>
18#include <QColorDialog>
21#include <klocalizedstring.h>
26#include <kconfiggroup.h>
27#include <ksharedconfig.h>
40 setMouseTracking(
true);
41 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
42 setFocusPolicy(Qt::WheelFocus);
47 QWindow *window = this->window()->windowHandle();
64 QPainter painter(
this);
73 painter.setRenderHint(QPainter::Antialiasing,
true);
75 const bool hasFocus = this->hasFocus();
79 QRectF segmentHandleRect =
81 selectedSegment->
startOffset() * handlesRect.width(),
83 -(handlesRect.width() - selectedSegment->
endOffset() * handlesRect.width()),
86 painter.fillRect(segmentHandleRect,
palette().highlight());
91 QRectF segmentHandleRect =
93 hoveredSegment->
startOffset() * handlesRect.width(),
95 -(handlesRect.width() - hoveredSegment->
endOffset() * handlesRect.width()),
98 QColor c =
palette().highlight().color();
100 painter.fillRect(segmentHandleRect, c);
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++) {
112 handlesRect.topLeft() +
113 QPointF(segments[i]->middleOffset() * handlesRect.width(), midPointHandleOffsetY);
115 painter, handlePos, midPointHandleSize,
121 const QColor highlightColor =
palette().color(QPalette::Highlight);
131 QPointF(handlesRect.left() + segment->
startOffset() * handlesRect.width(), handlesRect.top()),
136 { colorType, segment->startColor().toQColor() }
140 if (segments.size() > 1) {
141 for (
int i = 0; i < segments.count() - 1; ++i) {
159 QPointF(handlesRect.left() + currentSegment->
endOffset() * handlesRect.width(), handlesRect.top()),
163 { KisGradientWidgetsUtils::segmentEndPointTypeToColorType(currentSegment->endType()), currentSegment->endColor().toQColor() },
164 { KisGradientWidgetsUtils::segmentEndPointTypeToColorType(nextSegment->startType()), nextSegment->startColor().toQColor() }
169 QPointF(handlesRect.left() + currentSegment->
endOffset() * handlesRect.width(), handlesRect.top()),
173 { KisGradientWidgetsUtils::segmentEndPointTypeToColorType(currentSegment->endType()), currentSegment->endColor().toQColor() }
177 QPointF(handlesRect.left() + nextSegment->
startOffset() * handlesRect.width(), handlesRect.top()),
181 { KisGradientWidgetsUtils::segmentEndPointTypeToColorType(nextSegment->startType()), nextSegment->startColor().toQColor() }
193 QPointF(handlesRect.left() + segment->
endOffset() * handlesRect.width(), handlesRect.top()),
200 { colorType, segment->endColor().toQColor() }
206 handlesRect.topLeft() +
207 QPointF(segments[
m_selectedHandle.
index]->middleOffset() * handlesRect.width(), midPointHandleOffsetY);
209 painter, handlePos, midPointHandleSize,
210 true,
false, hasFocus,
221 QPointF(handlesRect.left() + segment->
startOffset() * handlesRect.width(), handlesRect.top()),
223 true,
false, hasFocus,
226 { colorType, segment->
startColor().toQColor() }
234 QPointF(handlesRect.left() + currentSegment->
endOffset() * handlesRect.width(), handlesRect.top()),
236 true,
false, hasFocus,
244 QPointF(handlesRect.left() + currentSegment->
endOffset() * handlesRect.width(), handlesRect.top()),
246 true,
false, hasFocus,
252 QPointF(handlesRect.left() + nextSegment->
startOffset() * handlesRect.width(), handlesRect.top()),
254 true,
false, hasFocus,
262 painter.setPen(
palette().color(QPalette::Mid));
263 painter.drawRect(previewRect);
269 if (e->button() != Qt::LeftButton) {
270 QWidget::mousePressEvent(e);
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());
283 for (
int i = 0; i <
m_gradient->segments().size(); ++i) {
286 if (qAbs(t - segment->
startOffset()) <= handleClickTolerance && e->pos().y() >= handlesRect.y()) {
292 }
else if (qAbs(t - segment->
endOffset()) <= handleClickTolerance && e->pos().y() >= handlesRect.y()) {
298 }
else if (qAbs(t - segment->
middleOffset()) <= handleClickTolerance && e->pos().y() >= handlesRect.y()) {
308 if (e->modifiers() & Qt::ControlModifier) {
316 m_gradient->segments()[i]->setEndColor(color);
317 m_gradient->segments()[i + 1]->setStartColor(color);
322 }
else if (e->modifiers() & Qt::ShiftModifier) {
354 const qreal t = (e->x() -
rect.left()) /
static_cast<qreal
>(
rect.width());
357 if (!(e->buttons() & Qt::LeftButton)) {
358 QWidget::mouseMoveEvent(e);
363 if (augmentedRect.contains(e->pos())) {
380 if (augmentedRect.contains(e->pos())) {
414 !augmentedRect.contains(e->pos())) {
432 if (previousSegment && nextSegment) {
434 const qreal previousMidPointLocalPos =
435 previousSegment->
length() > std::numeric_limits<qreal>::epsilon()
438 const qreal nextMidPointLocalPos =
439 nextSegment->
length() > std::numeric_limits<qreal>::epsilon()
442 qreal newStartOffset, newEndOffset;
445 newEndOffset = newStartOffset + segment->
length();
448 newStartOffset = newEndOffset - segment->
length();
456 previousMidPointLocalPos * previousSegment->
length()
460 nextMidPointLocalPos * nextSegment->
length()
464 if (!previousSegment) {
481 !augmentedRect.contains(e->pos())) {
503 if (previousSegment && nextSegment) {
504 const qreal previousMidPointLocalPos =
505 previousSegment->
length() > std::numeric_limits<qreal>::epsilon()
508 const qreal nextMidPointLocalPos =
509 nextSegment->
length() > std::numeric_limits<qreal>::epsilon()
522 previousMidPointLocalPos * previousSegment->
length()
526 nextMidPointLocalPos * nextSegment->
length()
529 if (!previousSegment) {
551 const qreal handleClickTolerance =
m_handleSize.width() /
static_cast<qreal
>(
rect.width());
552 for (
int i = 0; i <
m_gradient->segments().size(); ++i) {
555 if (qAbs(t - segment->
startOffset()) <= handleClickTolerance && e->pos().y() >= handlesRect.y()) {
558 hoveredHandle.
index = i;
560 }
else if (qAbs(t - segment->
endOffset()) <= handleClickTolerance && e->pos().y() >= handlesRect.y()) {
563 hoveredHandle.
index = i + 1;
565 }
else if (qAbs(t - segment->
middleOffset()) <= handleClickTolerance && e->pos().y() >= handlesRect.y()) {
568 hoveredHandle.
index = i;
573 hoveredHandle.
index = i;
584 if (e->button() != Qt::LeftButton) {
585 QWidget::mouseDoubleClickEvent(e);
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());
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())) {
644 if (direction == 0) {
647 if (modifiers & Qt::ControlModifier) {
654 const qreal increment = modifiers & Qt::ShiftModifier ? 0.001 : 0.01;
661 if (e->angleDelta().y() != 0) {
665 QWidget::wheelEvent(e);
686 QWidget::keyPressEvent(e);
695 QWidget::leaveEvent(e);
700 const qreal epsilon = useShrinkEpsilon ?
shrinkEpsilon : 0.0;
705 if (previousSegment && nextSegment) {
707 const qreal previousMidPointLocalPos =
708 previousSegment->
length() > std::numeric_limits<qreal>::epsilon()
711 const qreal nextMidPointLocalPos =
712 nextSegment->
length() > std::numeric_limits<qreal>::epsilon()
715 qreal newStartOffset, newEndOffset;
718 newEndOffset = newStartOffset + segment->
length();
721 newStartOffset = newEndOffset - segment->
length();
729 previousMidPointLocalPos * previousSegment->
length()
733 nextMidPointLocalPos * nextSegment->
length()
737 if (!previousSegment) {
749 if (previousSegment && nextSegment) {
750 const qreal previousMidPointLocalPos =
751 previousSegment->
length() > std::numeric_limits<qreal>::epsilon()
754 const qreal nextMidPointLocalPos =
755 nextSegment->
length() > std::numeric_limits<qreal>::epsilon()
768 previousMidPointLocalPos * previousSegment->
length()
772 nextMidPointLocalPos * nextSegment->
length()
775 if (!previousSegment) {
832 const qreal middleOffset = previousSegment->
endOffset();
877 if (previousSegment && nextSegment) {
885 if (previousSegment && nextSegment) {
930 for (
int i = oldSegments.size() - 1; i >= 0; --i) {
949 interpolation, colorInterpolation,
955 newSegments.push_back(newSegment);
969 const qreal size = 1.0 /
m_gradient->segments().size();
970 for (
int i = 0; i <
m_gradient->segments().size(); ++i) {
972 const qreal relativeMidPointPosition =
978 segment->
startOffset() + relativeMidPointPosition *
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);
995 return rc.adjusted(0, 0, 0, -
m_handleSize.height() - 4);
1001 return rc.adjusted(0, rc.height() - (
m_handleSize.height() + 2), 0, -2);
1006 QFontMetrics fm(font());
1007 const int h = qMax(15,
static_cast<int>(std::ceil(fm.height() * 0.75)));
1013 QFontMetrics fm(font());
1014 const int h = fm.height();
1016 QStyleOptionToolButton opt;
1017 QSize sz = style()->sizeFromContents(QStyle::CT_ToolButton, &opt, QSize(h, h),
this);
1025 return QSize(2 * h, h);
1047 endType1 = segments[0]->startType();
1048 color1 = segments[0]->startColor();
1058 KConfigGroup cfg = KSharedConfig::openConfig()->group(
"colorselector");
1059 bool usePlatformDialog = cfg.readEntry(
"UsePlatformColorDialog",
false);
1060 QDialog *colorDialog =
nullptr;
1062 if (!usePlatformDialog) {
1065 dialog->setPreviousColor(color1);
1066 auto setColorFn = [dialog, segments,
this]()
mutable
1070 segments[0]->setStartColor(dialog->getCurrentColor());
1083 connect(dialog, &QDialog::accepted, setColorFn);
1084 colorDialog = dialog;
1086 QColorDialog *dialog =
new QColorDialog(
this);
1087 dialog->setCurrentColor(color1.
toQColor());
1088 auto setColorFn = [dialog, segments,
this]()
mutable
1094 segments[0]->setStartColor(color);
1106 connect(dialog, &QColorDialog::currentColorChanged, setColorFn);
1107 connect(dialog, &QDialog::accepted, setColorFn);
1108 colorDialog = dialog;
1111 connect(colorDialog, &QDialog::rejected, [endType1, endType2, color1, color2, segments,
this]()
1114 segments[0]->setStartType(endType1);
1115 segments[0]->setStartColor(color1);
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);
1127 colorDialog->setAttribute(Qt::WA_DeleteOnClose);
1128 colorDialog->show();
1129 colorDialog->raise();
1130 colorDialog->activateWindow();
qreal distance(const QPointF &p1, const QPointF &p2)
KoGradientSegmentEndpointType
@ INTERP_SPHERE_DECREASING
@ INTERP_SPHERE_INCREASING
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
The KisInternalColorSelector class.
void signalForegroundColorChosen(KoColor color)
signalForegroundColorChosen The most important signal. This will sent out when a color has been chose...
void moveSelectedHandle(qreal distance, bool useShrinkEpsilon=true)
void leaveEvent(QEvent *e) override
void moveHandleLeft(Handle handle, qreal distance, bool useShrinkEpsilon=true)
KisSignalCompressor m_updateCompressor
void moveSelectedHandleRight(qreal distance, bool useShrinkEpsilon=true)
void mouseDoubleClickEvent(QMouseEvent *e) override
void selectPreviousHandle()
void chooseSelectedStopColor()
void mousePressEvent(QMouseEvent *e) override
static constexpr int removeStopDistance
static constexpr qreal shrinkEpsilon
void duplicateSelectedSegment()
QRect handlesStripeRect() const
void splitSelectedSegment()
KisSegmentGradientSlider(QWidget *parent=nullptr, const char *name=nullptr, Qt::WindowFlags f=Qt::WindowFlags())
void selectedHandleChanged()
void deleteHandle(Handle handle)
TemporallyDeletedHandleInfo m_temporallyDeletedHandleInfo
void mouseReleaseEvent(QMouseEvent *e) override
void collapseSelectedSegment()
void handleIncrementInput(int direction, Qt::KeyboardModifiers modifiers)
void centerSelectedHandle()
void setGradientResource(KoSegmentGradientSP agr)
void mirrorSelectedSegment()
qreal m_relativeDragOffset
void paintEvent(QPaintEvent *) override
KoSegmentGradientSP m_gradient
void keyPressEvent(QKeyEvent *e) override
void wheelEvent(QWheelEvent *e) override
QRect gradientStripeRect() const
QSize sizeHint() const override
void moveHandle(Handle handle, qreal distance, bool useShrinkEpsilon=true)
bool deleteHandleImpl(Handle handle)
void moveHandleRight(Handle handle, qreal distance, bool useShrinkEpsilon=true)
void distributeStopsEvenly()
int minimalHeight() const
void moveSelectedHandleLeft(qreal distance, bool useShrinkEpsilon=true)
void mouseMoveEvent(QMouseEvent *e) override
void deleteSelectedHandle()
QSize minimumSizeHint() const override
void fromQColor(const QColor &c)
Convenient function for converting from a QColor.
void toQColor(QColor *c) const
a convenience method for the above.
void setEndType(KoGradientSegmentEndpointType type)
int colorInterpolation() const
qreal startOffset() const
void setInterpolation(int interpolationType)
void setMiddleOffset(qreal t)
KoGradientSegmentEndpointType endType() const
void setColorInterpolation(int colorInterpolationType)
int interpolation() const
KoGradientSegmentEndpointType startType() const
void setStartColor(const KoColor &color)
void setStartType(KoGradientSegmentEndpointType type)
void setStartOffset(qreal t)
void setEndColor(const KoColor &color)
const KoColor & startColor() const
void setEndOffset(qreal t)
const KoColor & endColor() const
qreal middleOffset() const
T kisGrowRect(const T &rect, U offset)
rgba palette[MAX_PALETTE]
KoColor leftEndPointColor
int rightInterpolationType
KoGradientSegmentEndpointType rightEndPointType
int rightColorInterpolationType
int leftColorInterpolationType
qreal rightEndPointOffset
int leftInterpolationType
KoGradientSegmentEndpointType leftEndPointType
KoColor rightEndPointColor