Krita Source Code Documentation
Loading...
Searching...
No Matches
KisSegmentGradientEditor.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2004 Cyrille Berger <cberger@cberger.net>
3 * SPDX-FileCopyrightText: 2004 Sven Langkamp <sven.langkamp@gmail.com>
4 * SPDX-FileCopyrightText: 2021 Deif Lou <ginoba@gmail.com>
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9#include <QPainter>
10#include <QDoubleSpinBox>
11#include <QAction>
12#include <QDialog>
13#include <QMenu>
14
15#include <KoColorSpace.h>
17
18#include "kis_debug.h"
19
21
24
25#include <kis_icon_utils.h>
26#include <kis_signals_blocker.h>
28
30
32 : QWidget(parent)
33 , m_gradient(nullptr)
34 , m_canvasResourcesInterface(nullptr)
35{
36 setupUi(this);
37
38 QAction *selectPreviousHandleAction = new QAction(KisIconUtils::loadIcon("arrow-left"),
39 i18nc("Action to select previous handle in the segment gradient editor", "Select previous handle"), this);
40 selectPreviousHandleAction->setToolTip(selectPreviousHandleAction->text());
41 connect(selectPreviousHandleAction, SIGNAL(triggered()), gradientSlider, SLOT(selectPreviousHandle()));
42
43 QAction *selectNextHandleAction = new QAction(KisIconUtils::loadIcon("arrow-right"),
44 i18nc("Action to select next handle in the segment gradient editor", "Select next handle"), this);
45 selectNextHandleAction->setToolTip(selectNextHandleAction->text());
46 connect(selectNextHandleAction, SIGNAL(triggered()), gradientSlider, SLOT(selectNextHandle()));
47
48 m_editHandleAction = new QAction(KisIconUtils::loadIcon("document-edit"), i18nc("Button to edit the selected handle in the segment gradient editor", "Edit handle"), this);
49 m_editHandleAction->setToolTip(m_editHandleAction->text());
50 connect(m_editHandleAction, SIGNAL(triggered()), this, SLOT(editSelectedHandle()));
51
52 m_deleteSegmentAction = new QAction(KisIconUtils::loadIcon("edit-delete"),
53 i18nc("Action to delete the selected segment in the segment gradient editor", "Delete segment"), this);
55 connect(m_deleteSegmentAction, SIGNAL(triggered()), gradientSlider, SLOT(collapseSelectedSegment()));
56
57 m_flipSegmentAction = new QAction(KisIconUtils::loadIcon("transform_icons_mirror_x"),
58 i18nc("Action to flip the selected segment in the segment gradient editor", "Flip segment"), this);
59 m_flipSegmentAction->setToolTip(m_flipSegmentAction->text());
60 connect(m_flipSegmentAction, SIGNAL(triggered()), gradientSlider, SLOT(mirrorSelectedSegment()));
61
62 m_splitSegmentAction = new QAction(KisIconUtils::loadIcon("cut-item"),
63 i18nc("Action to split the selected segment in the segment gradient editor", "Split segment"), this);
64 m_splitSegmentAction->setToolTip(m_splitSegmentAction->text());
65 connect(m_splitSegmentAction, SIGNAL(triggered()), gradientSlider, SLOT(splitSelectedSegment()));
66
67 m_duplicateSegmentAction = new QAction(KisIconUtils::loadIcon("duplicateitem"),
68 i18nc("Action to duplicate the selected segment in the segment gradient editor", "Duplicate segment"), this);
70 connect(m_duplicateSegmentAction, SIGNAL(triggered()), gradientSlider, SLOT(duplicateSelectedSegment()));
71
72 m_deleteStopAction = new QAction(KisIconUtils::loadIcon("edit-delete"),
73 i18nc("Action to delete the selected stop in the segment gradient editor", "Delete stop"), this);
74 m_deleteStopAction->setToolTip(m_deleteStopAction->text());
75 connect(m_deleteStopAction, SIGNAL(triggered()), gradientSlider, SLOT(deleteSelectedHandle()));
76
77 m_centerStopAction = new QAction(KisIconUtils::loadIcon("object-align-horizontal-center-calligra"),
78 i18nc("Action to center the selected stop in the segment gradient editor", "Center stop"), this);
79 m_centerStopAction->setToolTip(m_centerStopAction->text());
80 connect(m_centerStopAction, SIGNAL(triggered()), gradientSlider, SLOT(centerSelectedHandle()));
81
82 m_centerMidPointAction = new QAction(KisIconUtils::loadIcon("object-align-horizontal-center-calligra"),
83 i18nc("Action to center the selected mid point in the segment gradient editor", "Center middle point"), this);
85 connect(m_centerMidPointAction, SIGNAL(triggered()), gradientSlider, SLOT(centerSelectedHandle()));
86
87 QAction *flipGradientAction = new QAction(KisIconUtils::loadIcon("transform_icons_mirror_x"),
88 i18nc("Button to flip the gradient in the segment gradient editor", "Flip gradient"), this);
89 flipGradientAction->setToolTip(flipGradientAction->text());
90 connect(flipGradientAction, SIGNAL(triggered()), gradientSlider, SLOT(flipGradient()));
91
92 QAction *distributeSegmentsEvenlyAction = new QAction(KisIconUtils::loadIcon("distribute-horizontal"),
93 i18nc("Button to evenly distribute the segments in the segment gradient editor", "Distribute segments evenly"), this);
94 distributeSegmentsEvenlyAction->setToolTip(distributeSegmentsEvenlyAction->text());
95 connect(distributeSegmentsEvenlyAction, SIGNAL(triggered()), gradientSlider, SLOT(distributeStopsEvenly()));
96
97 selectPreviousHandleButton->setAutoRaise(true);
98 selectPreviousHandleButton->setDefaultAction(selectPreviousHandleAction);
99
100 selectNextHandleButton->setAutoRaise(true);
101 selectNextHandleButton->setDefaultAction(selectNextHandleAction);
102
103 deleteSegmentButton->setAutoRaise(true);
104 deleteSegmentButton->setDefaultAction(m_deleteSegmentAction);
105
106 flipSegmentButton->setAutoRaise(true);
107 flipSegmentButton->setDefaultAction(m_flipSegmentAction);
108
109 splitSegmentButton->setAutoRaise(true);
110 splitSegmentButton->setDefaultAction(m_splitSegmentAction);
111
112 duplicateSegmentButton->setAutoRaise(true);
113 duplicateSegmentButton->setDefaultAction(m_duplicateSegmentAction);
114
115 deleteStopButton->setAutoRaise(true);
116 deleteStopButton->setDefaultAction(m_deleteStopAction);
117
118 centerStopButton->setAutoRaise(true);
119 centerStopButton->setDefaultAction(m_centerStopAction);
120
121 centerMidPointButton->setAutoRaise(true);
122 centerMidPointButton->setDefaultAction(m_centerMidPointAction);
123
124 flipGradientButton->setAutoRaise(true);
125 flipGradientButton->setDefaultAction(flipGradientAction);
126
127 distributeSegmentsEvenlyButton->setAutoRaise(true);
128 distributeSegmentsEvenlyButton->setDefaultAction(distributeSegmentsEvenlyAction);
129
130 compactModeSelectPreviousHandleButton->setAutoRaise(true);
131 compactModeSelectPreviousHandleButton->setDefaultAction(selectPreviousHandleAction);
132
133 compactModeSelectNextHandleButton->setAutoRaise(true);
134 compactModeSelectNextHandleButton->setDefaultAction(selectNextHandleAction);
135
136 compactModeMiscOptionsButton->setPopupMode(QToolButton::InstantPopup);
137 compactModeMiscOptionsButton->setArrowVisible(false);
138 compactModeMiscOptionsButton->setAutoRaise(true);
139 compactModeMiscOptionsButton->setIcon(KisIconUtils::loadIcon("view-choose"));
140 QMenu *compactModeMiscOptionsButtonMenu = new QMenu;
141 QAction *separator = new QAction;
142 separator->setSeparator(true);
143 compactModeMiscOptionsButtonMenu->addAction(m_editHandleAction);
144 compactModeMiscOptionsButtonMenu->addAction(m_deleteSegmentAction);
145 compactModeMiscOptionsButtonMenu->addAction(m_flipSegmentAction);
146 compactModeMiscOptionsButtonMenu->addAction(m_splitSegmentAction);
147 compactModeMiscOptionsButtonMenu->addAction(m_duplicateSegmentAction);
148 compactModeMiscOptionsButtonMenu->addAction(m_deleteStopAction);
149 compactModeMiscOptionsButtonMenu->addAction(m_centerStopAction);
150 compactModeMiscOptionsButtonMenu->addAction(m_centerMidPointAction);
151 compactModeMiscOptionsButtonMenu->addAction(separator);
152 compactModeMiscOptionsButtonMenu->addAction(flipGradientAction);
153 compactModeMiscOptionsButtonMenu->addAction(distributeSegmentsEvenlyAction);
154 compactModeMiscOptionsButton->setPopupWidget(compactModeMiscOptionsButtonMenu);
155
156 stopLeftEditor->setUsePositionSlider(false);
157 stopRightEditor->setUsePositionSlider(false);
158 constrainStopButton->setKeepAspectRatio(false);
159 constrainStopButton->setToolTip(i18nc("Button to link both end colors of a stop handle in the segment gradient editor", "Link colors"));
160 stopPositionSlider->setRange(0, 100, 2);
161 KisSpinBoxI18nHelper::setText(stopPositionSlider,
162 i18nc("{n} is the number value, % is the percent sign", "Position: {n}%"));
163 midPointPositionSlider->setRange(0, 100, 2);
164 KisSpinBoxI18nHelper::setText(midPointPositionSlider,
165 i18nc("{n} is the number value, % is the percent sign", "Position: {n}%"));
166
167 setCompactMode(false);
168 setGradient(0);
169}
170
171KisSegmentGradientEditor::KisSegmentGradientEditor(KoSegmentGradientSP gradient, QWidget *parent, const char* name, const QString& caption, KoCanvasResourcesInterfaceSP canvasResourcesInterface)
173{
175 setObjectName(name);
176 setWindowTitle(caption);
178}
179
181{
182 lblName->setVisible(!value);
183 nameedit->setVisible(!value);
184 buttonsContainer->setVisible(!value);
185 handleEditorContainer->setVisible(!value);
186 compactModeButtonsContainer->setVisible(value);
187}
188
190{
192 setEnabled(bool(m_gradient));
193
194 if (m_gradient) {
195 nameedit->setText(m_gradient->name());
196 gradientSlider->setGradientResource(m_gradient);
197 }
198
199 Q_EMIT sigGradientChanged();
200}
201
206
211
213{
214 KisSegmentGradientSlider::Handle handle = gradientSlider->selectedHandle();
215
217 KoGradientSegment *segment = m_gradient->segments()[handle.index];
218
219 KisSignalsBlocker blocker(
220 segmentLeftEditor, segmentRightEditor,
221 segmentInterpolationTypeComboBox, segmentColorInterpolationTypeComboBox
222 );
223
224 selectedHandleLabel->setText(i18nc("Text that indicates the selected segment in the segment gradient editor", "Segment #%1", handle.index + 1));
225
226 segmentLeftEditor->setColorType(KisGradientWidgetsUtils::segmentEndPointTypeToColorType(segment->startType()));
227 segmentLeftEditor->setTransparent(segment->startType() == FOREGROUND_TRANSPARENT_ENDPOINT ||
229 segmentLeftEditor->setColor(segment->startColor());
230 segmentLeftEditor->setOpacity(segment->startColor().opacityF() * 100.0);
231 segmentLeftEditor->setPosition(segment->startOffset() * 100.0);
232 segmentLeftEditor->setPositionSliderEnabled(handle.index > 0);
233
234 segmentRightEditor->setColorType(KisGradientWidgetsUtils::segmentEndPointTypeToColorType(segment->endType()));
235 segmentRightEditor->setTransparent(segment->endType() == FOREGROUND_TRANSPARENT_ENDPOINT ||
237 segmentRightEditor->setColor(segment->endColor());
238 segmentRightEditor->setOpacity(segment->endColor().opacityF() * 100.0);
239 segmentRightEditor->setPosition(segment->endOffset() * 100.0);
240 segmentRightEditor->setPositionSliderEnabled(handle.index < m_gradient->segments().size() - 1);
241
242 segmentInterpolationTypeComboBox->setCurrentIndex(segment->interpolation());
243 segmentColorInterpolationTypeComboBox->setCurrentIndex(segment->colorInterpolation());
244
245 handleEditorContainer->setCurrentIndex(0);
246
247 m_deleteSegmentAction->setEnabled(m_gradient->segments().size() > 1);
248
249 } else if (handle.type == KisSegmentGradientSlider::HandleType_Stop) {
250 KoGradientSegment *previousSegment = handle.index == 0 ? nullptr : m_gradient->segments()[handle.index - 1];
251 KoGradientSegment *nextSegment = handle.index == m_gradient->segments().size() ? nullptr : m_gradient->segments()[handle.index];
252
253 KisSignalsBlocker blocker(stopLeftEditor, stopRightEditor, constrainStopButton, stopPositionSlider);
254
255 selectedHandleLabel->setText(i18nc("Text that indicates the selected stop in the segment gradient editor", "Stop #%1", handle.index + 1));
256
257 if (previousSegment) {
258 stopLeftEditor->setColorType(KisGradientWidgetsUtils::segmentEndPointTypeToColorType(previousSegment->endType()));
259 stopLeftEditor->setTransparent(previousSegment->endType() == FOREGROUND_TRANSPARENT_ENDPOINT ||
260 previousSegment->endType() == BACKGROUND_TRANSPARENT_ENDPOINT);
261 stopLeftEditor->setColor(previousSegment->endColor());
262 stopLeftEditor->setOpacity(previousSegment->endColor().opacityF() * 100.0);
263 }
264 stopLeftEditor->setEnabled(previousSegment);
265
266 if (nextSegment) {
267 stopRightEditor->setColorType(KisGradientWidgetsUtils::segmentEndPointTypeToColorType(nextSegment->startType()));
268 stopRightEditor->setTransparent(nextSegment->startType() == FOREGROUND_TRANSPARENT_ENDPOINT ||
270 stopRightEditor->setColor(nextSegment->startColor());
271 stopRightEditor->setOpacity(nextSegment->startColor().opacityF() * 100.0);
272 }
273 stopRightEditor->setEnabled(nextSegment);
274
275 if (previousSegment && nextSegment) {
276 constrainStopButton->setKeepAspectRatio(
277 previousSegment->endType() == nextSegment->startType() &&
278 previousSegment->endColor() == nextSegment->startColor()
279 );
280 }
281 constrainStopButton->setEnabled(previousSegment && nextSegment);
282 if (previousSegment) {
283 stopPositionSlider->setValue(previousSegment->endOffset() * 100.0);
284 } else if (nextSegment) {
285 stopPositionSlider->setValue(nextSegment->startOffset() * 100.0);
286 }
287 stopPositionSlider->setEnabled(previousSegment && nextSegment);
288
289 handleEditorContainer->setCurrentIndex(1);
290
291 m_deleteStopAction->setEnabled(previousSegment && nextSegment);
292 m_centerStopAction->setEnabled(previousSegment && nextSegment);
293
295 KoGradientSegment *segment = m_gradient->segments()[handle.index];
296
297 KisSignalsBlocker blocker(midPointPositionSlider);
298
299 selectedHandleLabel->setText(i18nc("Text that indicates the selected mid point in the segment gradient editor", "Mid-Point #%1", handle.index + 1));
300
301 midPointPositionSlider->setValue(
302 (segment->middleOffset() - segment->startOffset()) / (segment->endOffset() - segment->startOffset()) * 100.0
303 );
304
305 handleEditorContainer->setCurrentIndex(2);
306
307 } else {
308 selectedHandleLabel->setText(i18nc("Text that indicates no handle is selected in the stop gradient editor", "No handle selected"));
309 handleEditorContainer->setCurrentIndex(3);
310 }
311
313
318 segmentButtonsContainer->setVisible(handle.type == KisSegmentGradientSlider::HandleType_Segment);
319
322 stopButtonsContainer->setVisible(handle.type == KisSegmentGradientSlider::HandleType_Stop);
323
325 midPointButtonsContainer->setVisible(handle.type == KisSegmentGradientSlider::HandleType_MidPoint);
326
327 Q_EMIT sigGradientChanged();
328}
329
331{
332 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) {
333 return;
334 }
335 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index];
336 KisSegmentGradientSlider::Handle stopHandle{KisSegmentGradientSlider::HandleType_Stop, gradientSlider->selectedHandle().index};
337 {
338 KisSignalsBlocker blocker(gradientSlider, segmentLeftEditor);
339 gradientSlider->moveHandle(stopHandle, position / 100.0 - segment->startOffset());
340 // Set the clamped value
341 segmentLeftEditor->setPosition(segment->startOffset() * 100.0);
342 }
343 Q_EMIT gradientSlider->updateRequested();
344 Q_EMIT sigGradientChanged();
345}
346
348{
349 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) {
350 return;
351 }
352
353 KoGradientSegmentEndpointType endPointType = KisGradientWidgetsUtils::colorTypeToSegmentEndPointType(type, segmentLeftEditor->transparent());
354 KoColor color;
355 const qreal opacity = segmentLeftEditor->transparent() ? 0.0 : 1.0;
356 const KoColorSpace* colorSpace = m_gradient->colorSpace();
357
358 if (endPointType == FOREGROUND_ENDPOINT || endPointType == FOREGROUND_TRANSPARENT_ENDPOINT) {
360 color = m_canvasResourcesInterface->resource(KoCanvasResource::ForegroundColor).value<KoColor>().convertedTo(colorSpace);
361 } else {
362 color = KoColor(segmentLeftEditor->color(), colorSpace);
363 }
364 } else if (endPointType == BACKGROUND_ENDPOINT || endPointType == BACKGROUND_TRANSPARENT_ENDPOINT) {
366 color = m_canvasResourcesInterface->resource(KoCanvasResource::BackgroundColor).value<KoColor>().convertedTo(colorSpace);
367 } else {
368 color = KoColor(segmentLeftEditor->color(), colorSpace);
369 }
370 } else {
371 color = KoColor(segmentLeftEditor->color(), colorSpace);
372 }
373
374 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index];
375 segment->setStartType(endPointType);
376 color.setOpacity(opacity);
377 segment->setStartColor(color);
378
379 segmentLeftEditor->setColor(color);
380 segmentLeftEditor->setOpacity(opacity * 100.0);
381
382 Q_EMIT gradientSlider->updateRequested();
383 Q_EMIT sigGradientChanged();
384}
385
387{
388 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) {
389 return;
390 }
391 const qreal opacity = checked ? 0.0 : 1.0;
392 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index];
393 segment->setStartType(KisGradientWidgetsUtils::colorTypeToSegmentEndPointType(segmentLeftEditor->colorType(), checked));
394 KoColor color = segment->startColor();
395 color.setOpacity(opacity);
396 segment->setStartColor(color);
397 segmentLeftEditor->setOpacity(opacity * 100.0);
398 Q_EMIT gradientSlider->updateRequested();
399 Q_EMIT sigGradientChanged();
400}
401
403{
404 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) {
405 return;
406 }
407 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index];
408 KoColor c(color, segment->startColor().colorSpace());
409 c.setOpacity(segmentLeftEditor->opacity() / 100.0);
410 segment->setStartColor(c);
411 Q_EMIT gradientSlider->updateRequested();
412 Q_EMIT sigGradientChanged();
413}
414
416{
417 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) {
418 return;
419 }
420 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index];
421 KoColor color = segment->startColor();
422 color.setOpacity(opacity / 100.0);
423 segment->setStartColor(color);
424 Q_EMIT gradientSlider->updateRequested();
425 Q_EMIT sigGradientChanged();
426}
427
429{
430 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) {
431 return;
432 }
433 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index];
434 KisSegmentGradientSlider::Handle stopHandle{KisSegmentGradientSlider::HandleType_Stop, gradientSlider->selectedHandle().index + 1};
435 {
436 KisSignalsBlocker blocker(gradientSlider, segmentLeftEditor);
437 gradientSlider->moveHandle(stopHandle, position / 100.0 - segment->endOffset());
438 // Set the clamped value
439 segmentLeftEditor->setPosition(segment->startOffset() * 100.0);
440 }
441 Q_EMIT gradientSlider->updateRequested();
442 Q_EMIT sigGradientChanged();
443}
444
446{
447 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) {
448 return;
449 }
450
451 KoGradientSegmentEndpointType endPointType = KisGradientWidgetsUtils::colorTypeToSegmentEndPointType(type, segmentRightEditor->transparent());
452 KoColor color;
453 const qreal opacity = segmentRightEditor->transparent() ? 0.0 : 1.0;
454 const KoColorSpace* colorSpace = m_gradient->colorSpace();
455
456 if (endPointType == FOREGROUND_ENDPOINT || endPointType == FOREGROUND_TRANSPARENT_ENDPOINT) {
458 color = m_canvasResourcesInterface->resource(KoCanvasResource::ForegroundColor).value<KoColor>().convertedTo(colorSpace);
459 } else {
460 color = KoColor(segmentRightEditor->color(), colorSpace);
461 }
462 } else if (endPointType == BACKGROUND_ENDPOINT || endPointType == BACKGROUND_TRANSPARENT_ENDPOINT) {
464 color = m_canvasResourcesInterface->resource(KoCanvasResource::BackgroundColor).value<KoColor>().convertedTo(colorSpace);
465 } else {
466 color = KoColor(segmentRightEditor->color(), colorSpace);
467 }
468 } else {
469 color = KoColor(segmentRightEditor->color(), colorSpace);
470 }
471
472 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index];
473 segment->setEndType(endPointType);
474 color.setOpacity(opacity);
475 segment->setEndColor(color);
476
477 segmentRightEditor->setColor(color);
478 segmentRightEditor->setOpacity(opacity * 100.0);
479
480 Q_EMIT gradientSlider->updateRequested();
481 Q_EMIT sigGradientChanged();
482}
483
485{
486 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) {
487 return;
488 }
489 const qreal opacity = checked ? 0.0 : 1.0;
490 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index];
491 segment->setEndType(KisGradientWidgetsUtils::colorTypeToSegmentEndPointType(segmentRightEditor->colorType(), checked));
492 KoColor color = segment->endColor();
493 color.setOpacity(opacity);
494 segment->setEndColor(color);
495 segmentRightEditor->setOpacity(opacity * 100.0);
496 Q_EMIT gradientSlider->updateRequested();
497 Q_EMIT sigGradientChanged();
498}
499
501{
502 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) {
503 return;
504 }
505 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index];
506 KoColor c(color, segment->endColor().colorSpace());
507 c.setOpacity(segmentRightEditor->opacity() / 100.0);
508 segment->setEndColor(c);
509 Q_EMIT gradientSlider->updateRequested();
510 Q_EMIT sigGradientChanged();
511}
512
514{
515 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) {
516 return;
517 }
518 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index];
519 KoColor color = segment->endColor();
520 color.setOpacity(opacity / 100.0);
521 segment->setEndColor(color);
522 Q_EMIT gradientSlider->updateRequested();
523 Q_EMIT sigGradientChanged();
524}
525
527{
528 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) {
529 return;
530 }
531 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index];
532 segment->setInterpolation(value);
533 Q_EMIT gradientSlider->updateRequested();
534 Q_EMIT sigGradientChanged();
535}
536
538{
539 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) {
540 return;
541 }
542 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index];
544 Q_EMIT gradientSlider->updateRequested();
545 Q_EMIT sigGradientChanged();
546}
547
549{
550 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Stop) {
551 return;
552 }
553 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index];
554 {
555 KisSignalsBlocker blocker(gradientSlider, stopPositionSlider);
556 gradientSlider->moveSelectedHandle(position / 100.0 - segment->startOffset());
557 // Set the clamped value
558 stopPositionSlider->setValue(segment->startOffset() * 100.0);
559 }
560 Q_EMIT gradientSlider->updateRequested();
561 Q_EMIT sigGradientChanged();
562}
563
565{
566 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Stop) {
567 return;
568 }
569
570 KoGradientSegmentEndpointType endPointType = KisGradientWidgetsUtils::colorTypeToSegmentEndPointType(type, stopLeftEditor->transparent());
571 KoColor color;
572 const qreal opacity = stopLeftEditor->transparent() ? 0.0 : 1.0;
573 const KoColorSpace* colorSpace = m_gradient->colorSpace();
574
575 if (endPointType == FOREGROUND_ENDPOINT || endPointType == FOREGROUND_TRANSPARENT_ENDPOINT) {
577 color = m_canvasResourcesInterface->resource(KoCanvasResource::ForegroundColor).value<KoColor>().convertedTo(colorSpace);
578 } else {
579 color = KoColor(stopLeftEditor->color(), colorSpace);
580 }
581 } else if (endPointType == BACKGROUND_ENDPOINT || endPointType == BACKGROUND_TRANSPARENT_ENDPOINT) {
583 color = m_canvasResourcesInterface->resource(KoCanvasResource::BackgroundColor).value<KoColor>().convertedTo(colorSpace);
584 } else {
585 color = KoColor(stopLeftEditor->color(), colorSpace);
586 }
587 } else {
588 color = KoColor(stopLeftEditor->color(), colorSpace);
589 }
590
591 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index - 1];
592 segment->setEndType(endPointType);
593 color.setOpacity(opacity);
594 segment->setEndColor(color);
595
596 stopLeftEditor->setColor(color);
597 stopLeftEditor->setOpacity(opacity * 100.0);
598
599 Q_EMIT gradientSlider->updateRequested();
600 Q_EMIT sigGradientChanged();
601
602 if (constrainStopButton->keepAspectRatio() &&
603 gradientSlider->selectedHandle().index < m_gradient->segments().size()) {
604 stopRightEditor->setColorType(stopLeftEditor->colorType());
605 }
606}
607
609{
610 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Stop) {
611 return;
612 }
613 const qreal opacity = checked ? 0.0 : 1.0;
614 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index - 1];
615 segment->setEndType(KisGradientWidgetsUtils::colorTypeToSegmentEndPointType(stopLeftEditor->colorType(), checked));
616 KoColor color = segment->endColor();
617 color.setOpacity(opacity);
618 segment->setEndColor(color);
619 stopLeftEditor->setOpacity(opacity * 100.0);
620 Q_EMIT gradientSlider->updateRequested();
621 Q_EMIT sigGradientChanged();
622 if (constrainStopButton->keepAspectRatio() &&
623 gradientSlider->selectedHandle().index < m_gradient->segments().size()) {
624 stopRightEditor->setTransparent(stopLeftEditor->transparent());
625 }
626}
627
629{
630 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Stop) {
631 return;
632 }
633 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index - 1];
634 KoColor c(color, segment->endColor().colorSpace());
635 c.setOpacity(stopLeftEditor->opacity() / 100.0);
636 segment->setEndColor(c);
637 Q_EMIT gradientSlider->updateRequested();
638 Q_EMIT sigGradientChanged();
639 if (constrainStopButton->keepAspectRatio() &&
640 gradientSlider->selectedHandle().index < m_gradient->segments().size()) {
641 stopRightEditor->setColor(stopLeftEditor->color());
642 }
643}
644
646{
647 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Stop) {
648 return;
649 }
650 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index - 1];
651 KoColor color = segment->endColor();
652 color.setOpacity(opacity / 100.0);
653 segment->setEndColor(color);
654 Q_EMIT gradientSlider->updateRequested();
655 Q_EMIT sigGradientChanged();
656 if (constrainStopButton->keepAspectRatio() &&
657 gradientSlider->selectedHandle().index < m_gradient->segments().size()) {
658 stopRightEditor->setOpacity(stopLeftEditor->opacity());
659 }
660}
661
663{
664 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Stop) {
665 return;
666 }
667
668 KoGradientSegmentEndpointType endPointType = KisGradientWidgetsUtils::colorTypeToSegmentEndPointType(type, stopRightEditor->transparent());
669 KoColor color;
670 const qreal opacity = stopRightEditor->transparent() ? 0.0 : 1.0;
671 const KoColorSpace* colorSpace = m_gradient->colorSpace();
672
673 if (endPointType == FOREGROUND_ENDPOINT || endPointType == FOREGROUND_TRANSPARENT_ENDPOINT) {
675 color = m_canvasResourcesInterface->resource(KoCanvasResource::ForegroundColor).value<KoColor>().convertedTo(colorSpace);
676 } else {
677 color = KoColor(stopRightEditor->color(), colorSpace);
678 }
679 } else if (endPointType == BACKGROUND_ENDPOINT || endPointType == BACKGROUND_TRANSPARENT_ENDPOINT) {
681 color = m_canvasResourcesInterface->resource(KoCanvasResource::BackgroundColor).value<KoColor>().convertedTo(colorSpace);
682 } else {
683 color = KoColor(stopRightEditor->color(), colorSpace);
684 }
685 } else {
686 color = KoColor(stopRightEditor->color(), colorSpace);
687 }
688
689 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index];
690 segment->setStartType(endPointType);
691 color.setOpacity(opacity);
692 segment->setStartColor(color);
693
694 stopRightEditor->setColor(color);
695 stopRightEditor->setOpacity(opacity * 100.0);
696
697 Q_EMIT gradientSlider->updateRequested();
698 Q_EMIT sigGradientChanged();
699
700 if (constrainStopButton->keepAspectRatio() && gradientSlider->selectedHandle().index > 0) {
701 stopLeftEditor->setColorType(stopRightEditor->colorType());
702 }
703}
704
706{
707 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Stop) {
708 return;
709 }
710 const qreal opacity = checked ? 0.0 : 1.0;
711 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index];
712 segment->setStartType(KisGradientWidgetsUtils::colorTypeToSegmentEndPointType(stopRightEditor->colorType(), checked));
713 KoColor color = segment->startColor();
714 color.setOpacity(opacity);
715 segment->setStartColor(color);
716 stopRightEditor->setOpacity(opacity * 100.0);
717 Q_EMIT gradientSlider->updateRequested();
718 Q_EMIT sigGradientChanged();
719 if (constrainStopButton->keepAspectRatio() && gradientSlider->selectedHandle().index > 0) {
720 stopLeftEditor->setTransparent(stopRightEditor->transparent());
721 }
722}
723
725{
726 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Stop) {
727 return;
728 }
729 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index];
730 KoColor c(color, segment->startColor().colorSpace());
731 c.setOpacity(stopRightEditor->opacity() / 100.0);
732 segment->setStartColor(c);
733 Q_EMIT gradientSlider->updateRequested();
734 Q_EMIT sigGradientChanged();
735 if (constrainStopButton->keepAspectRatio() && gradientSlider->selectedHandle().index > 0) {
736 stopLeftEditor->setColor(stopRightEditor->color());
737 }
738}
739
741{
742 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Stop) {
743 return;
744 }
745 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index];
746 KoColor color = segment->startColor();
747 color.setOpacity(opacity / 100.0);
748 segment->setStartColor(color);
749 Q_EMIT gradientSlider->updateRequested();
750 Q_EMIT sigGradientChanged();
751 if (constrainStopButton->keepAspectRatio() && gradientSlider->selectedHandle().index > 0) {
752 stopLeftEditor->setOpacity(stopRightEditor->opacity());
753 }
754}
755
757{
758 if (!keep || gradientSlider->selectedHandle().index == m_gradient->segments().size()) {
759 return;
760 }
761 stopRightEditor->setColorType(stopLeftEditor->colorType());
762 stopRightEditor->setTransparent(stopLeftEditor->transparent());
763 stopRightEditor->setColor(stopLeftEditor->color());
764 stopRightEditor->setOpacity(stopLeftEditor->opacity());
765 Q_EMIT sigGradientChanged();
766}
767
769{
770 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_MidPoint) {
771 return;
772 }
773 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index];
774 segment->setMiddleOffset(segment->startOffset() + (position / 100.0) * (segment->endOffset() - segment->startOffset()));
775 Q_EMIT gradientSlider->updateRequested();
776 Q_EMIT sigGradientChanged();
777}
778
780{
781 m_gradient->setName(nameedit->text());
782 m_gradient->setFilename(nameedit->text() + m_gradient->defaultFileExtension());
783 Q_EMIT sigGradientChanged();
784}
785
787{
788 if (gradientSlider->selectedHandle().type == KisSegmentGradientSlider::HandleType_None) {
789 return;
790 }
791
792 QDialog *dialog = new QDialog(this);
793 dialog->setModal(true);
794 dialog->setWindowTitle(i18nc("Title for the segment gradient handle editor", "Edit Handle"));
795 dialog->setAttribute(Qt::WA_DeleteOnClose);
796
797 QWidget *editor = handleEditorContainer->currentWidget();
798 int index = handleEditorContainer->indexOf(editor);
799 handleEditorContainer->removeWidget(editor);
800
801 QVBoxLayout *dialogLayout = new QVBoxLayout;
802 dialogLayout->setContentsMargins(10, 10, 10, 10);
803 dialogLayout->addWidget(editor);
804
805 dialog->setLayout(dialogLayout);
806 editor->show();
807 dialog->resize(0, 0);
808
809 connect(dialog, &QDialog::finished, [this, editor, index](int)
810 {
811 handleEditorContainer->insertWidget(index, editor);
812 handleEditorContainer->setCurrentIndex(index);
813 });
814
815 dialog->show();
816 dialog->raise();
817 dialog->activateWindow();
818}
float value(const T *src, size_t ch)
KoGradientSegmentEndpointType
@ BACKGROUND_TRANSPARENT_ENDPOINT
@ FOREGROUND_ENDPOINT
@ BACKGROUND_ENDPOINT
@ FOREGROUND_TRANSPARENT_ENDPOINT
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
void on_segmentColorInterpolationTypeComboBox_activated(int value)
void on_segmentInterpolationTypeComboBox_activated(int value)
void on_stopRightEditor_colorTypeChanged(KisGradientWidgetsUtils::ColorType type)
void on_stopLeftEditor_colorChanged(KoColor color)
void setCanvasResourcesInterface(KoCanvasResourcesInterfaceSP canvasResourcesInterface)
KoCanvasResourcesInterfaceSP canvasResourcesInterface() const
void on_stopLeftEditor_transparentToggled(bool checked)
void on_segmentLeftEditor_positionChanged(double position)
void on_segmentLeftEditor_transparentToggled(bool checked)
void on_midPointPositionSlider_valueChanged(double opacity)
void on_stopLeftEditor_colorTypeChanged(KisGradientWidgetsUtils::ColorType type)
void on_segmentLeftEditor_colorTypeChanged(KisGradientWidgetsUtils::ColorType type)
void on_segmentLeftEditor_colorChanged(KoColor color)
void on_constrainStopButton_keepAspectRatioChanged(bool keep)
void on_segmentRightEditor_positionChanged(double position)
void on_stopPositionSlider_valueChanged(double position)
void on_stopRightEditor_transparentToggled(bool checked)
void on_segmentRightEditor_opacityChanged(double opacity)
void on_segmentLeftEditor_opacityChanged(double opacity)
void on_segmentRightEditor_colorChanged(KoColor color)
void setGradient(KoSegmentGradientSP gradient)
void on_segmentRightEditor_transparentToggled(bool checked)
void on_stopRightEditor_opacityChanged(double opacity)
void on_segmentRightEditor_colorTypeChanged(KisGradientWidgetsUtils::ColorType type)
KoCanvasResourcesInterfaceSP m_canvasResourcesInterface
void on_stopLeftEditor_opacityChanged(double opacity)
void on_stopRightEditor_colorChanged(KoColor color)
qreal opacityF() const
Definition KoColor.cpp:345
void setOpacity(quint8 alpha)
Definition KoColor.cpp:333
const KoColorSpace * colorSpace() const
return the current colorSpace
Definition KoColor.h:82
Write API docs here.
void setEndType(KoGradientSegmentEndpointType type)
void setInterpolation(int interpolationType)
void setMiddleOffset(qreal t)
KoGradientSegmentEndpointType endType() const
void setColorInterpolation(int colorInterpolationType)
KoGradientSegmentEndpointType startType() const
void setStartColor(const KoColor &color)
void setStartType(KoGradientSegmentEndpointType type)
void setEndColor(const KoColor &color)
const KoColor & startColor() const
const KoColor & endColor() const
KisGradientWidgetsUtils::ColorType segmentEndPointTypeToColorType(KoGradientSegmentEndpointType type)
KoGradientSegmentEndpointType colorTypeToSegmentEndPointType(KisGradientWidgetsUtils::ColorType type, bool transparent)
QIcon loadIcon(const QString &name)
void setText(QSpinBox *spinBox, const QStringView textTemplate)
@ BackgroundColor
The active background color selected for this canvas.
@ ForegroundColor
The active foreground color selected for this canvas.