File indexing completed on 2024-12-22 04:13:06
0001 /* 0002 * SPDX-FileCopyrightText: 2004 Cyrille Berger <cberger@cberger.net> 0003 * SPDX-FileCopyrightText: 2004 Sven Langkamp <sven.langkamp@gmail.com> 0004 * SPDX-FileCopyrightText: 2021 Deif Lou <ginoba@gmail.com> 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include <QPainter> 0010 #include <QComboBox> 0011 #include <QDoubleSpinBox> 0012 #include <QAction> 0013 #include <QDialog> 0014 #include <QMenu> 0015 0016 #include <KoColorSpace.h> 0017 #include <resources/KoSegmentGradient.h> 0018 0019 #include "kis_debug.h" 0020 0021 #include "KisSegmentGradientSlider.h" 0022 0023 #include <KoCanvasResourcesIds.h> 0024 #include <KoCanvasResourcesInterface.h> 0025 0026 #include <kis_icon_utils.h> 0027 #include <kis_signals_blocker.h> 0028 #include <KisSpinBoxI18nHelper.h> 0029 0030 #include "KisSegmentGradientEditor.h" 0031 0032 KisSegmentGradientEditor::KisSegmentGradientEditor(QWidget *parent) 0033 : QWidget(parent) 0034 , m_gradient(nullptr) 0035 , m_canvasResourcesInterface(nullptr) 0036 { 0037 setupUi(this); 0038 0039 QAction *selectPreviousHandleAction = new QAction(KisIconUtils::loadIcon("arrow-left"), 0040 i18nc("Action to select previous handle in the segment gradient editor", "Select previous handle"), this); 0041 selectPreviousHandleAction->setToolTip(selectPreviousHandleAction->text()); 0042 connect(selectPreviousHandleAction, SIGNAL(triggered()), gradientSlider, SLOT(selectPreviousHandle())); 0043 0044 QAction *selectNextHandleAction = new QAction(KisIconUtils::loadIcon("arrow-right"), 0045 i18nc("Action to select next handle in the segment gradient editor", "Select next handle"), this); 0046 selectNextHandleAction->setToolTip(selectNextHandleAction->text()); 0047 connect(selectNextHandleAction, SIGNAL(triggered()), gradientSlider, SLOT(selectNextHandle())); 0048 0049 m_editHandleAction = new QAction(KisIconUtils::loadIcon("document-edit"), i18nc("Button to edit the selected handle in the segment gradient editor", "Edit handle"), this); 0050 m_editHandleAction->setToolTip(m_editHandleAction->text()); 0051 connect(m_editHandleAction, SIGNAL(triggered()), this, SLOT(editSelectedHandle())); 0052 0053 m_deleteSegmentAction = new QAction(KisIconUtils::loadIcon("edit-delete"), 0054 i18nc("Action to delete the selected segment in the segment gradient editor", "Delete segment"), this); 0055 m_deleteSegmentAction->setToolTip(m_deleteSegmentAction->text()); 0056 connect(m_deleteSegmentAction, SIGNAL(triggered()), gradientSlider, SLOT(collapseSelectedSegment())); 0057 0058 m_flipSegmentAction = new QAction(KisIconUtils::loadIcon("transform_icons_mirror_x"), 0059 i18nc("Action to flip the selected segment in the segment gradient editor", "Flip segment"), this); 0060 m_flipSegmentAction->setToolTip(m_flipSegmentAction->text()); 0061 connect(m_flipSegmentAction, SIGNAL(triggered()), gradientSlider, SLOT(mirrorSelectedSegment())); 0062 0063 m_splitSegmentAction = new QAction(KisIconUtils::loadIcon("cut-item"), 0064 i18nc("Action to split the selected segment in the segment gradient editor", "Split segment"), this); 0065 m_splitSegmentAction->setToolTip(m_splitSegmentAction->text()); 0066 connect(m_splitSegmentAction, SIGNAL(triggered()), gradientSlider, SLOT(splitSelectedSegment())); 0067 0068 m_duplicateSegmentAction = new QAction(KisIconUtils::loadIcon("duplicateitem"), 0069 i18nc("Action to duplicate the selected segment in the segment gradient editor", "Duplicate segment"), this); 0070 m_duplicateSegmentAction->setToolTip(m_duplicateSegmentAction->text()); 0071 connect(m_duplicateSegmentAction, SIGNAL(triggered()), gradientSlider, SLOT(duplicateSelectedSegment())); 0072 0073 m_deleteStopAction = new QAction(KisIconUtils::loadIcon("edit-delete"), 0074 i18nc("Action to delete the selected stop in the segment gradient editor", "Delete stop"), this); 0075 m_deleteStopAction->setToolTip(m_deleteStopAction->text()); 0076 connect(m_deleteStopAction, SIGNAL(triggered()), gradientSlider, SLOT(deleteSelectedHandle())); 0077 0078 m_centerStopAction = new QAction(KisIconUtils::loadIcon("object-align-horizontal-center-calligra"), 0079 i18nc("Action to center the selected stop in the segment gradient editor", "Center stop"), this); 0080 m_centerStopAction->setToolTip(m_centerStopAction->text()); 0081 connect(m_centerStopAction, SIGNAL(triggered()), gradientSlider, SLOT(centerSelectedHandle())); 0082 0083 m_centerMidPointAction = new QAction(KisIconUtils::loadIcon("object-align-horizontal-center-calligra"), 0084 i18nc("Action to center the selected mid point in the segment gradient editor", "Center middle point"), this); 0085 m_centerMidPointAction->setToolTip(m_centerMidPointAction->text()); 0086 connect(m_centerMidPointAction, SIGNAL(triggered()), gradientSlider, SLOT(centerSelectedHandle())); 0087 0088 QAction *flipGradientAction = new QAction(KisIconUtils::loadIcon("transform_icons_mirror_x"), 0089 i18nc("Button to flip the gradient in the segment gradient editor", "Flip gradient"), this); 0090 flipGradientAction->setToolTip(flipGradientAction->text()); 0091 connect(flipGradientAction, SIGNAL(triggered()), gradientSlider, SLOT(flipGradient())); 0092 0093 QAction *distributeSegmentsEvenlyAction = new QAction(KisIconUtils::loadIcon("distribute-horizontal"), 0094 i18nc("Button to evenly distribute the segments in the segment gradient editor", "Distribute segments evenly"), this); 0095 distributeSegmentsEvenlyAction->setToolTip(distributeSegmentsEvenlyAction->text()); 0096 connect(distributeSegmentsEvenlyAction, SIGNAL(triggered()), gradientSlider, SLOT(distributeStopsEvenly())); 0097 0098 selectPreviousHandleButton->setAutoRaise(true); 0099 selectPreviousHandleButton->setDefaultAction(selectPreviousHandleAction); 0100 0101 selectNextHandleButton->setAutoRaise(true); 0102 selectNextHandleButton->setDefaultAction(selectNextHandleAction); 0103 0104 deleteSegmentButton->setAutoRaise(true); 0105 deleteSegmentButton->setDefaultAction(m_deleteSegmentAction); 0106 0107 flipSegmentButton->setAutoRaise(true); 0108 flipSegmentButton->setDefaultAction(m_flipSegmentAction); 0109 0110 splitSegmentButton->setAutoRaise(true); 0111 splitSegmentButton->setDefaultAction(m_splitSegmentAction); 0112 0113 duplicateSegmentButton->setAutoRaise(true); 0114 duplicateSegmentButton->setDefaultAction(m_duplicateSegmentAction); 0115 0116 deleteStopButton->setAutoRaise(true); 0117 deleteStopButton->setDefaultAction(m_deleteStopAction); 0118 0119 centerStopButton->setAutoRaise(true); 0120 centerStopButton->setDefaultAction(m_centerStopAction); 0121 0122 centerMidPointButton->setAutoRaise(true); 0123 centerMidPointButton->setDefaultAction(m_centerMidPointAction); 0124 0125 flipGradientButton->setAutoRaise(true); 0126 flipGradientButton->setDefaultAction(flipGradientAction); 0127 0128 distributeSegmentsEvenlyButton->setAutoRaise(true); 0129 distributeSegmentsEvenlyButton->setDefaultAction(distributeSegmentsEvenlyAction); 0130 0131 compactModeSelectPreviousHandleButton->setAutoRaise(true); 0132 compactModeSelectPreviousHandleButton->setDefaultAction(selectPreviousHandleAction); 0133 0134 compactModeSelectNextHandleButton->setAutoRaise(true); 0135 compactModeSelectNextHandleButton->setDefaultAction(selectNextHandleAction); 0136 0137 compactModeMiscOptionsButton->setPopupMode(QToolButton::InstantPopup); 0138 compactModeMiscOptionsButton->setArrowVisible(false); 0139 compactModeMiscOptionsButton->setAutoRaise(true); 0140 compactModeMiscOptionsButton->setIcon(KisIconUtils::loadIcon("view-choose")); 0141 QMenu *compactModeMiscOptionsButtonMenu = new QMenu; 0142 QAction *separator = new QAction; 0143 separator->setSeparator(true); 0144 compactModeMiscOptionsButtonMenu->addAction(m_editHandleAction); 0145 compactModeMiscOptionsButtonMenu->addAction(m_deleteSegmentAction); 0146 compactModeMiscOptionsButtonMenu->addAction(m_flipSegmentAction); 0147 compactModeMiscOptionsButtonMenu->addAction(m_splitSegmentAction); 0148 compactModeMiscOptionsButtonMenu->addAction(m_duplicateSegmentAction); 0149 compactModeMiscOptionsButtonMenu->addAction(m_deleteStopAction); 0150 compactModeMiscOptionsButtonMenu->addAction(m_centerStopAction); 0151 compactModeMiscOptionsButtonMenu->addAction(m_centerMidPointAction); 0152 compactModeMiscOptionsButtonMenu->addAction(separator); 0153 compactModeMiscOptionsButtonMenu->addAction(flipGradientAction); 0154 compactModeMiscOptionsButtonMenu->addAction(distributeSegmentsEvenlyAction); 0155 compactModeMiscOptionsButton->setPopupWidget(compactModeMiscOptionsButtonMenu); 0156 0157 stopLeftEditor->setUsePositionSlider(false); 0158 stopRightEditor->setUsePositionSlider(false); 0159 constrainStopButton->setKeepAspectRatio(false); 0160 constrainStopButton->setToolTip(i18nc("Button to link both end colors of a stop handle in the segment gradient editor", "Link colors")); 0161 stopPositionSlider->setRange(0, 100, 2); 0162 KisSpinBoxI18nHelper::setText(stopPositionSlider, 0163 i18nc("{n} is the number value, % is the percent sign", "Position: {n}%")); 0164 midPointPositionSlider->setRange(0, 100, 2); 0165 KisSpinBoxI18nHelper::setText(midPointPositionSlider, 0166 i18nc("{n} is the number value, % is the percent sign", "Position: {n}%")); 0167 0168 setCompactMode(false); 0169 setGradient(0); 0170 } 0171 0172 KisSegmentGradientEditor::KisSegmentGradientEditor(KoSegmentGradientSP gradient, QWidget *parent, const char* name, const QString& caption, KoCanvasResourcesInterfaceSP canvasResourcesInterface) 0173 : KisSegmentGradientEditor(parent) 0174 { 0175 m_canvasResourcesInterface = canvasResourcesInterface; 0176 setObjectName(name); 0177 setWindowTitle(caption); 0178 setGradient(gradient); 0179 } 0180 0181 void KisSegmentGradientEditor::setCompactMode(bool value) 0182 { 0183 lblName->setVisible(!value); 0184 nameedit->setVisible(!value); 0185 buttonsContainer->setVisible(!value); 0186 handleEditorContainer->setVisible(!value); 0187 compactModeButtonsContainer->setVisible(value); 0188 } 0189 0190 void KisSegmentGradientEditor::setGradient(KoSegmentGradientSP gradient) 0191 { 0192 m_gradient = gradient; 0193 setEnabled(m_gradient); 0194 0195 if (m_gradient) { 0196 nameedit->setText(m_gradient->name()); 0197 gradientSlider->setGradientResource(m_gradient); 0198 } 0199 0200 emit sigGradientChanged(); 0201 } 0202 0203 void KisSegmentGradientEditor::setCanvasResourcesInterface(KoCanvasResourcesInterfaceSP canvasResourcesInterface) 0204 { 0205 m_canvasResourcesInterface = canvasResourcesInterface; 0206 } 0207 0208 KoCanvasResourcesInterfaceSP KisSegmentGradientEditor::canvasResourcesInterface() const 0209 { 0210 return m_canvasResourcesInterface; 0211 } 0212 0213 void KisSegmentGradientEditor::on_gradientSlider_selectedHandleChanged() 0214 { 0215 KisSegmentGradientSlider::Handle handle = gradientSlider->selectedHandle(); 0216 0217 if (handle.type == KisSegmentGradientSlider::HandleType_Segment) { 0218 KoGradientSegment *segment = m_gradient->segments()[handle.index]; 0219 0220 KisSignalsBlocker blocker( 0221 segmentLeftEditor, segmentRightEditor, 0222 segmentInterpolationTypeComboBox, segmentColorInterpolationTypeComboBox 0223 ); 0224 0225 selectedHandleLabel->setText(i18nc("Text that indicates the selected segment in the segment gradient editor", "Segment #%1", handle.index + 1)); 0226 0227 segmentLeftEditor->setColorType(KisGradientWidgetsUtils::segmentEndPointTypeToColorType(segment->startType())); 0228 segmentLeftEditor->setTransparent(segment->startType() == FOREGROUND_TRANSPARENT_ENDPOINT || 0229 segment->startType() == BACKGROUND_TRANSPARENT_ENDPOINT); 0230 segmentLeftEditor->setColor(segment->startColor()); 0231 segmentLeftEditor->setOpacity(segment->startColor().opacityF() * 100.0); 0232 segmentLeftEditor->setPosition(segment->startOffset() * 100.0); 0233 segmentLeftEditor->setPositionSliderEnabled(handle.index > 0); 0234 0235 segmentRightEditor->setColorType(KisGradientWidgetsUtils::segmentEndPointTypeToColorType(segment->endType())); 0236 segmentRightEditor->setTransparent(segment->endType() == FOREGROUND_TRANSPARENT_ENDPOINT || 0237 segment->endType() == BACKGROUND_TRANSPARENT_ENDPOINT); 0238 segmentRightEditor->setColor(segment->endColor()); 0239 segmentRightEditor->setOpacity(segment->endColor().opacityF() * 100.0); 0240 segmentRightEditor->setPosition(segment->endOffset() * 100.0); 0241 segmentRightEditor->setPositionSliderEnabled(handle.index < m_gradient->segments().size() - 1); 0242 0243 segmentInterpolationTypeComboBox->setCurrentIndex(segment->interpolation()); 0244 segmentColorInterpolationTypeComboBox->setCurrentIndex(segment->colorInterpolation()); 0245 0246 handleEditorContainer->setCurrentIndex(0); 0247 0248 m_deleteSegmentAction->setEnabled(m_gradient->segments().size() > 1); 0249 0250 } else if (handle.type == KisSegmentGradientSlider::HandleType_Stop) { 0251 KoGradientSegment *previousSegment = handle.index == 0 ? nullptr : m_gradient->segments()[handle.index - 1]; 0252 KoGradientSegment *nextSegment = handle.index == m_gradient->segments().size() ? nullptr : m_gradient->segments()[handle.index]; 0253 0254 KisSignalsBlocker blocker(stopLeftEditor, stopRightEditor, constrainStopButton, stopPositionSlider); 0255 0256 selectedHandleLabel->setText(i18nc("Text that indicates the selected stop in the segment gradient editor", "Stop #%1", handle.index + 1)); 0257 0258 if (previousSegment) { 0259 stopLeftEditor->setColorType(KisGradientWidgetsUtils::segmentEndPointTypeToColorType(previousSegment->endType())); 0260 stopLeftEditor->setTransparent(previousSegment->endType() == FOREGROUND_TRANSPARENT_ENDPOINT || 0261 previousSegment->endType() == BACKGROUND_TRANSPARENT_ENDPOINT); 0262 stopLeftEditor->setColor(previousSegment->endColor()); 0263 stopLeftEditor->setOpacity(previousSegment->endColor().opacityF() * 100.0); 0264 } 0265 stopLeftEditor->setEnabled(previousSegment); 0266 0267 if (nextSegment) { 0268 stopRightEditor->setColorType(KisGradientWidgetsUtils::segmentEndPointTypeToColorType(nextSegment->startType())); 0269 stopRightEditor->setTransparent(nextSegment->startType() == FOREGROUND_TRANSPARENT_ENDPOINT || 0270 nextSegment->startType() == BACKGROUND_TRANSPARENT_ENDPOINT); 0271 stopRightEditor->setColor(nextSegment->startColor()); 0272 stopRightEditor->setOpacity(nextSegment->startColor().opacityF() * 100.0); 0273 } 0274 stopRightEditor->setEnabled(nextSegment); 0275 0276 if (previousSegment && nextSegment) { 0277 constrainStopButton->setKeepAspectRatio( 0278 previousSegment->endType() == nextSegment->startType() && 0279 previousSegment->endColor() == nextSegment->startColor() 0280 ); 0281 } 0282 constrainStopButton->setEnabled(previousSegment && nextSegment); 0283 if (previousSegment) { 0284 stopPositionSlider->setValue(previousSegment->endOffset() * 100.0); 0285 } else if (nextSegment) { 0286 stopPositionSlider->setValue(nextSegment->startOffset() * 100.0); 0287 } 0288 stopPositionSlider->setEnabled(previousSegment && nextSegment); 0289 0290 handleEditorContainer->setCurrentIndex(1); 0291 0292 m_deleteStopAction->setEnabled(previousSegment && nextSegment); 0293 m_centerStopAction->setEnabled(previousSegment && nextSegment); 0294 0295 } else if (handle.type == KisSegmentGradientSlider::HandleType_MidPoint) { 0296 KoGradientSegment *segment = m_gradient->segments()[handle.index]; 0297 0298 KisSignalsBlocker blocker(midPointPositionSlider); 0299 0300 selectedHandleLabel->setText(i18nc("Text that indicates the selected mid point in the segment gradient editor", "Mid-Point #%1", handle.index + 1)); 0301 0302 midPointPositionSlider->setValue( 0303 (segment->middleOffset() - segment->startOffset()) / (segment->endOffset() - segment->startOffset()) * 100.0 0304 ); 0305 0306 handleEditorContainer->setCurrentIndex(2); 0307 0308 } else { 0309 selectedHandleLabel->setText(i18nc("Text that indicates no handle is selected in the stop gradient editor", "No handle selected")); 0310 handleEditorContainer->setCurrentIndex(3); 0311 } 0312 0313 m_editHandleAction->setEnabled(handle.type != KisSegmentGradientSlider::HandleType_None); 0314 0315 m_deleteSegmentAction->setVisible(handle.type == KisSegmentGradientSlider::HandleType_Segment); 0316 m_flipSegmentAction->setVisible(handle.type == KisSegmentGradientSlider::HandleType_Segment); 0317 m_splitSegmentAction->setVisible(handle.type == KisSegmentGradientSlider::HandleType_Segment); 0318 m_duplicateSegmentAction->setVisible(handle.type == KisSegmentGradientSlider::HandleType_Segment); 0319 segmentButtonsContainer->setVisible(handle.type == KisSegmentGradientSlider::HandleType_Segment); 0320 0321 m_deleteStopAction->setVisible(handle.type == KisSegmentGradientSlider::HandleType_Stop); 0322 m_centerStopAction->setVisible(handle.type == KisSegmentGradientSlider::HandleType_Stop); 0323 stopButtonsContainer->setVisible(handle.type == KisSegmentGradientSlider::HandleType_Stop); 0324 0325 m_centerMidPointAction->setVisible(handle.type == KisSegmentGradientSlider::HandleType_MidPoint); 0326 midPointButtonsContainer->setVisible(handle.type == KisSegmentGradientSlider::HandleType_MidPoint); 0327 0328 emit sigGradientChanged(); 0329 } 0330 0331 void KisSegmentGradientEditor::on_segmentLeftEditor_positionChanged(double position) 0332 { 0333 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) { 0334 return; 0335 } 0336 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index]; 0337 KisSegmentGradientSlider::Handle stopHandle{KisSegmentGradientSlider::HandleType_Stop, gradientSlider->selectedHandle().index}; 0338 { 0339 KisSignalsBlocker blocker(gradientSlider, segmentLeftEditor); 0340 gradientSlider->moveHandle(stopHandle, position / 100.0 - segment->startOffset()); 0341 // Set the clamped value 0342 segmentLeftEditor->setPosition(segment->startOffset() * 100.0); 0343 } 0344 emit gradientSlider->updateRequested(); 0345 emit sigGradientChanged(); 0346 } 0347 0348 void KisSegmentGradientEditor::on_segmentLeftEditor_colorTypeChanged(KisGradientWidgetsUtils::ColorType type) 0349 { 0350 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) { 0351 return; 0352 } 0353 0354 KoGradientSegmentEndpointType endPointType = KisGradientWidgetsUtils::colorTypeToSegmentEndPointType(type, segmentLeftEditor->transparent()); 0355 KoColor color; 0356 const qreal opacity = segmentLeftEditor->transparent() ? 0.0 : 1.0; 0357 const KoColorSpace* colorSpace = m_gradient->colorSpace(); 0358 0359 if (endPointType == FOREGROUND_ENDPOINT || endPointType == FOREGROUND_TRANSPARENT_ENDPOINT) { 0360 if (m_canvasResourcesInterface) { 0361 color = m_canvasResourcesInterface->resource(KoCanvasResource::ForegroundColor).value<KoColor>().convertedTo(colorSpace); 0362 } else { 0363 color = KoColor(segmentLeftEditor->color(), colorSpace); 0364 } 0365 } else if (endPointType == BACKGROUND_ENDPOINT || endPointType == BACKGROUND_TRANSPARENT_ENDPOINT) { 0366 if (m_canvasResourcesInterface) { 0367 color = m_canvasResourcesInterface->resource(KoCanvasResource::BackgroundColor).value<KoColor>().convertedTo(colorSpace); 0368 } else { 0369 color = KoColor(segmentLeftEditor->color(), colorSpace); 0370 } 0371 } else { 0372 color = KoColor(segmentLeftEditor->color(), colorSpace); 0373 } 0374 0375 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index]; 0376 segment->setStartType(endPointType); 0377 color.setOpacity(opacity); 0378 segment->setStartColor(color); 0379 0380 segmentLeftEditor->setColor(color); 0381 segmentLeftEditor->setOpacity(opacity * 100.0); 0382 0383 emit gradientSlider->updateRequested(); 0384 emit sigGradientChanged(); 0385 } 0386 0387 void KisSegmentGradientEditor::on_segmentLeftEditor_transparentToggled(bool checked) 0388 { 0389 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) { 0390 return; 0391 } 0392 const qreal opacity = checked ? 0.0 : 1.0; 0393 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index]; 0394 segment->setStartType(KisGradientWidgetsUtils::colorTypeToSegmentEndPointType(segmentLeftEditor->colorType(), checked)); 0395 KoColor color = segment->startColor(); 0396 color.setOpacity(opacity); 0397 segment->setStartColor(color); 0398 segmentLeftEditor->setOpacity(opacity * 100.0); 0399 emit gradientSlider->updateRequested(); 0400 emit sigGradientChanged(); 0401 } 0402 0403 void KisSegmentGradientEditor::on_segmentLeftEditor_colorChanged(KoColor color) 0404 { 0405 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) { 0406 return; 0407 } 0408 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index]; 0409 KoColor c(color, segment->startColor().colorSpace()); 0410 c.setOpacity(segmentLeftEditor->opacity() / 100.0); 0411 segment->setStartColor(c); 0412 emit gradientSlider->updateRequested(); 0413 emit sigGradientChanged(); 0414 } 0415 0416 void KisSegmentGradientEditor::on_segmentLeftEditor_opacityChanged(double opacity) 0417 { 0418 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) { 0419 return; 0420 } 0421 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index]; 0422 KoColor color = segment->startColor(); 0423 color.setOpacity(opacity / 100.0); 0424 segment->setStartColor(color); 0425 emit gradientSlider->updateRequested(); 0426 emit sigGradientChanged(); 0427 } 0428 0429 void KisSegmentGradientEditor::on_segmentRightEditor_positionChanged(double position) 0430 { 0431 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) { 0432 return; 0433 } 0434 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index]; 0435 KisSegmentGradientSlider::Handle stopHandle{KisSegmentGradientSlider::HandleType_Stop, gradientSlider->selectedHandle().index + 1}; 0436 { 0437 KisSignalsBlocker blocker(gradientSlider, segmentLeftEditor); 0438 gradientSlider->moveHandle(stopHandle, position / 100.0 - segment->endOffset()); 0439 // Set the clamped value 0440 segmentLeftEditor->setPosition(segment->startOffset() * 100.0); 0441 } 0442 emit gradientSlider->updateRequested(); 0443 emit sigGradientChanged(); 0444 } 0445 0446 void KisSegmentGradientEditor::on_segmentRightEditor_colorTypeChanged(KisGradientWidgetsUtils::ColorType type) 0447 { 0448 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) { 0449 return; 0450 } 0451 0452 KoGradientSegmentEndpointType endPointType = KisGradientWidgetsUtils::colorTypeToSegmentEndPointType(type, segmentRightEditor->transparent()); 0453 KoColor color; 0454 const qreal opacity = segmentRightEditor->transparent() ? 0.0 : 1.0; 0455 const KoColorSpace* colorSpace = m_gradient->colorSpace(); 0456 0457 if (endPointType == FOREGROUND_ENDPOINT || endPointType == FOREGROUND_TRANSPARENT_ENDPOINT) { 0458 if (m_canvasResourcesInterface) { 0459 color = m_canvasResourcesInterface->resource(KoCanvasResource::ForegroundColor).value<KoColor>().convertedTo(colorSpace); 0460 } else { 0461 color = KoColor(segmentRightEditor->color(), colorSpace); 0462 } 0463 } else if (endPointType == BACKGROUND_ENDPOINT || endPointType == BACKGROUND_TRANSPARENT_ENDPOINT) { 0464 if (m_canvasResourcesInterface) { 0465 color = m_canvasResourcesInterface->resource(KoCanvasResource::BackgroundColor).value<KoColor>().convertedTo(colorSpace); 0466 } else { 0467 color = KoColor(segmentRightEditor->color(), colorSpace); 0468 } 0469 } else { 0470 color = KoColor(segmentRightEditor->color(), colorSpace); 0471 } 0472 0473 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index]; 0474 segment->setEndType(endPointType); 0475 color.setOpacity(opacity); 0476 segment->setEndColor(color); 0477 0478 segmentRightEditor->setColor(color); 0479 segmentRightEditor->setOpacity(opacity * 100.0); 0480 0481 emit gradientSlider->updateRequested(); 0482 emit sigGradientChanged(); 0483 } 0484 0485 void KisSegmentGradientEditor::on_segmentRightEditor_transparentToggled(bool checked) 0486 { 0487 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) { 0488 return; 0489 } 0490 const qreal opacity = checked ? 0.0 : 1.0; 0491 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index]; 0492 segment->setEndType(KisGradientWidgetsUtils::colorTypeToSegmentEndPointType(segmentRightEditor->colorType(), checked)); 0493 KoColor color = segment->endColor(); 0494 color.setOpacity(opacity); 0495 segment->setEndColor(color); 0496 segmentRightEditor->setOpacity(opacity * 100.0); 0497 emit gradientSlider->updateRequested(); 0498 emit sigGradientChanged(); 0499 } 0500 0501 void KisSegmentGradientEditor::on_segmentRightEditor_colorChanged(KoColor color) 0502 { 0503 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) { 0504 return; 0505 } 0506 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index]; 0507 KoColor c(color, segment->endColor().colorSpace()); 0508 c.setOpacity(segmentRightEditor->opacity() / 100.0); 0509 segment->setEndColor(c); 0510 emit gradientSlider->updateRequested(); 0511 emit sigGradientChanged(); 0512 } 0513 0514 void KisSegmentGradientEditor::on_segmentRightEditor_opacityChanged(double opacity) 0515 { 0516 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) { 0517 return; 0518 } 0519 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index]; 0520 KoColor color = segment->endColor(); 0521 color.setOpacity(opacity / 100.0); 0522 segment->setEndColor(color); 0523 emit gradientSlider->updateRequested(); 0524 emit sigGradientChanged(); 0525 } 0526 0527 void KisSegmentGradientEditor::on_segmentInterpolationTypeComboBox_activated(int value) 0528 { 0529 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) { 0530 return; 0531 } 0532 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index]; 0533 segment->setInterpolation(value); 0534 emit gradientSlider->updateRequested(); 0535 emit sigGradientChanged(); 0536 } 0537 0538 void KisSegmentGradientEditor::on_segmentColorInterpolationTypeComboBox_activated(int value) 0539 { 0540 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Segment) { 0541 return; 0542 } 0543 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index]; 0544 segment->setColorInterpolation(value); 0545 emit gradientSlider->updateRequested(); 0546 emit sigGradientChanged(); 0547 } 0548 0549 void KisSegmentGradientEditor::on_stopPositionSlider_valueChanged(double position) 0550 { 0551 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Stop) { 0552 return; 0553 } 0554 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index]; 0555 { 0556 KisSignalsBlocker blocker(gradientSlider, stopPositionSlider); 0557 gradientSlider->moveSelectedHandle(position / 100.0 - segment->startOffset()); 0558 // Set the clamped value 0559 stopPositionSlider->setValue(segment->startOffset() * 100.0); 0560 } 0561 emit gradientSlider->updateRequested(); 0562 emit sigGradientChanged(); 0563 } 0564 0565 void KisSegmentGradientEditor::on_stopLeftEditor_colorTypeChanged(KisGradientWidgetsUtils::ColorType type) 0566 { 0567 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Stop) { 0568 return; 0569 } 0570 0571 KoGradientSegmentEndpointType endPointType = KisGradientWidgetsUtils::colorTypeToSegmentEndPointType(type, stopLeftEditor->transparent()); 0572 KoColor color; 0573 const qreal opacity = stopLeftEditor->transparent() ? 0.0 : 1.0; 0574 const KoColorSpace* colorSpace = m_gradient->colorSpace(); 0575 0576 if (endPointType == FOREGROUND_ENDPOINT || endPointType == FOREGROUND_TRANSPARENT_ENDPOINT) { 0577 if (m_canvasResourcesInterface) { 0578 color = m_canvasResourcesInterface->resource(KoCanvasResource::ForegroundColor).value<KoColor>().convertedTo(colorSpace); 0579 } else { 0580 color = KoColor(stopLeftEditor->color(), colorSpace); 0581 } 0582 } else if (endPointType == BACKGROUND_ENDPOINT || endPointType == BACKGROUND_TRANSPARENT_ENDPOINT) { 0583 if (m_canvasResourcesInterface) { 0584 color = m_canvasResourcesInterface->resource(KoCanvasResource::BackgroundColor).value<KoColor>().convertedTo(colorSpace); 0585 } else { 0586 color = KoColor(stopLeftEditor->color(), colorSpace); 0587 } 0588 } else { 0589 color = KoColor(stopLeftEditor->color(), colorSpace); 0590 } 0591 0592 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index - 1]; 0593 segment->setEndType(endPointType); 0594 color.setOpacity(opacity); 0595 segment->setEndColor(color); 0596 0597 stopLeftEditor->setColor(color); 0598 stopLeftEditor->setOpacity(opacity * 100.0); 0599 0600 emit gradientSlider->updateRequested(); 0601 emit sigGradientChanged(); 0602 0603 if (constrainStopButton->keepAspectRatio() && 0604 gradientSlider->selectedHandle().index < m_gradient->segments().size()) { 0605 stopRightEditor->setColorType(stopLeftEditor->colorType()); 0606 } 0607 } 0608 0609 void KisSegmentGradientEditor::on_stopLeftEditor_transparentToggled(bool checked) 0610 { 0611 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Stop) { 0612 return; 0613 } 0614 const qreal opacity = checked ? 0.0 : 1.0; 0615 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index - 1]; 0616 segment->setEndType(KisGradientWidgetsUtils::colorTypeToSegmentEndPointType(stopLeftEditor->colorType(), checked)); 0617 KoColor color = segment->endColor(); 0618 color.setOpacity(opacity); 0619 segment->setEndColor(color); 0620 stopLeftEditor->setOpacity(opacity * 100.0); 0621 emit gradientSlider->updateRequested(); 0622 emit sigGradientChanged(); 0623 if (constrainStopButton->keepAspectRatio() && 0624 gradientSlider->selectedHandle().index < m_gradient->segments().size()) { 0625 stopRightEditor->setTransparent(stopLeftEditor->transparent()); 0626 } 0627 } 0628 0629 void KisSegmentGradientEditor::on_stopLeftEditor_colorChanged(KoColor color) 0630 { 0631 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Stop) { 0632 return; 0633 } 0634 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index - 1]; 0635 KoColor c(color, segment->endColor().colorSpace()); 0636 c.setOpacity(stopLeftEditor->opacity() / 100.0); 0637 segment->setEndColor(c); 0638 emit gradientSlider->updateRequested(); 0639 emit sigGradientChanged(); 0640 if (constrainStopButton->keepAspectRatio() && 0641 gradientSlider->selectedHandle().index < m_gradient->segments().size()) { 0642 stopRightEditor->setColor(stopLeftEditor->color()); 0643 } 0644 } 0645 0646 void KisSegmentGradientEditor::on_stopLeftEditor_opacityChanged(double opacity) 0647 { 0648 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Stop) { 0649 return; 0650 } 0651 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index - 1]; 0652 KoColor color = segment->endColor(); 0653 color.setOpacity(opacity / 100.0); 0654 segment->setEndColor(color); 0655 emit gradientSlider->updateRequested(); 0656 emit sigGradientChanged(); 0657 if (constrainStopButton->keepAspectRatio() && 0658 gradientSlider->selectedHandle().index < m_gradient->segments().size()) { 0659 stopRightEditor->setOpacity(stopLeftEditor->opacity()); 0660 } 0661 } 0662 0663 void KisSegmentGradientEditor::on_stopRightEditor_colorTypeChanged(KisGradientWidgetsUtils::ColorType type) 0664 { 0665 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Stop) { 0666 return; 0667 } 0668 0669 KoGradientSegmentEndpointType endPointType = KisGradientWidgetsUtils::colorTypeToSegmentEndPointType(type, stopRightEditor->transparent()); 0670 KoColor color; 0671 const qreal opacity = stopRightEditor->transparent() ? 0.0 : 1.0; 0672 const KoColorSpace* colorSpace = m_gradient->colorSpace(); 0673 0674 if (endPointType == FOREGROUND_ENDPOINT || endPointType == FOREGROUND_TRANSPARENT_ENDPOINT) { 0675 if (m_canvasResourcesInterface) { 0676 color = m_canvasResourcesInterface->resource(KoCanvasResource::ForegroundColor).value<KoColor>().convertedTo(colorSpace); 0677 } else { 0678 color = KoColor(stopRightEditor->color(), colorSpace); 0679 } 0680 } else if (endPointType == BACKGROUND_ENDPOINT || endPointType == BACKGROUND_TRANSPARENT_ENDPOINT) { 0681 if (m_canvasResourcesInterface) { 0682 color = m_canvasResourcesInterface->resource(KoCanvasResource::BackgroundColor).value<KoColor>().convertedTo(colorSpace); 0683 } else { 0684 color = KoColor(stopRightEditor->color(), colorSpace); 0685 } 0686 } else { 0687 color = KoColor(stopRightEditor->color(), colorSpace); 0688 } 0689 0690 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index]; 0691 segment->setStartType(endPointType); 0692 color.setOpacity(opacity); 0693 segment->setStartColor(color); 0694 0695 stopRightEditor->setColor(color); 0696 stopRightEditor->setOpacity(opacity * 100.0); 0697 0698 emit gradientSlider->updateRequested(); 0699 emit sigGradientChanged(); 0700 0701 if (constrainStopButton->keepAspectRatio() && gradientSlider->selectedHandle().index > 0) { 0702 stopLeftEditor->setColorType(stopRightEditor->colorType()); 0703 } 0704 } 0705 0706 void KisSegmentGradientEditor::on_stopRightEditor_transparentToggled(bool checked) 0707 { 0708 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Stop) { 0709 return; 0710 } 0711 const qreal opacity = checked ? 0.0 : 1.0; 0712 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index]; 0713 segment->setStartType(KisGradientWidgetsUtils::colorTypeToSegmentEndPointType(stopRightEditor->colorType(), checked)); 0714 KoColor color = segment->startColor(); 0715 color.setOpacity(opacity); 0716 segment->setStartColor(color); 0717 stopRightEditor->setOpacity(opacity * 100.0); 0718 emit gradientSlider->updateRequested(); 0719 emit sigGradientChanged(); 0720 if (constrainStopButton->keepAspectRatio() && gradientSlider->selectedHandle().index > 0) { 0721 stopLeftEditor->setTransparent(stopRightEditor->transparent()); 0722 } 0723 } 0724 0725 void KisSegmentGradientEditor::on_stopRightEditor_colorChanged(KoColor color) 0726 { 0727 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Stop) { 0728 return; 0729 } 0730 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index]; 0731 KoColor c(color, segment->startColor().colorSpace()); 0732 c.setOpacity(stopRightEditor->opacity() / 100.0); 0733 segment->setStartColor(c); 0734 emit gradientSlider->updateRequested(); 0735 emit sigGradientChanged(); 0736 if (constrainStopButton->keepAspectRatio() && gradientSlider->selectedHandle().index > 0) { 0737 stopLeftEditor->setColor(stopRightEditor->color()); 0738 } 0739 } 0740 0741 void KisSegmentGradientEditor::on_stopRightEditor_opacityChanged(double opacity) 0742 { 0743 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_Stop) { 0744 return; 0745 } 0746 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index]; 0747 KoColor color = segment->startColor(); 0748 color.setOpacity(opacity / 100.0); 0749 segment->setStartColor(color); 0750 emit gradientSlider->updateRequested(); 0751 emit sigGradientChanged(); 0752 if (constrainStopButton->keepAspectRatio() && gradientSlider->selectedHandle().index > 0) { 0753 stopLeftEditor->setOpacity(stopRightEditor->opacity()); 0754 } 0755 } 0756 0757 void KisSegmentGradientEditor::on_constrainStopButton_keepAspectRatioChanged(bool keep) 0758 { 0759 if (!keep || gradientSlider->selectedHandle().index == m_gradient->segments().size()) { 0760 return; 0761 } 0762 stopRightEditor->setColorType(stopLeftEditor->colorType()); 0763 stopRightEditor->setTransparent(stopLeftEditor->transparent()); 0764 stopRightEditor->setColor(stopLeftEditor->color()); 0765 stopRightEditor->setOpacity(stopLeftEditor->opacity()); 0766 emit sigGradientChanged(); 0767 } 0768 0769 void KisSegmentGradientEditor::on_midPointPositionSlider_valueChanged(double position) 0770 { 0771 if (gradientSlider->selectedHandle().type != KisSegmentGradientSlider::HandleType_MidPoint) { 0772 return; 0773 } 0774 KoGradientSegment *segment = m_gradient->segments()[gradientSlider->selectedHandle().index]; 0775 segment->setMiddleOffset(segment->startOffset() + (position / 100.0) * (segment->endOffset() - segment->startOffset())); 0776 emit gradientSlider->updateRequested(); 0777 emit sigGradientChanged(); 0778 } 0779 0780 void KisSegmentGradientEditor::on_nameedit_editingFinished() 0781 { 0782 m_gradient->setName(nameedit->text()); 0783 m_gradient->setFilename(nameedit->text() + m_gradient->defaultFileExtension()); 0784 emit sigGradientChanged(); 0785 } 0786 0787 void KisSegmentGradientEditor::editSelectedHandle() 0788 { 0789 if (gradientSlider->selectedHandle().type == KisSegmentGradientSlider::HandleType_None) { 0790 return; 0791 } 0792 0793 QDialog *dialog = new QDialog(this); 0794 dialog->setModal(true); 0795 dialog->setWindowTitle(i18nc("Title for the segment gradient handle editor", "Edit Handle")); 0796 dialog->setAttribute(Qt::WA_DeleteOnClose); 0797 0798 QWidget *editor = handleEditorContainer->currentWidget(); 0799 int index = handleEditorContainer->indexOf(editor); 0800 handleEditorContainer->removeWidget(editor); 0801 0802 QVBoxLayout *dialogLayout = new QVBoxLayout; 0803 dialogLayout->setMargin(10); 0804 dialogLayout->addWidget(editor); 0805 0806 dialog->setLayout(dialogLayout); 0807 editor->show(); 0808 dialog->resize(0, 0); 0809 0810 connect(dialog, &QDialog::finished, [this, editor, index](int) 0811 { 0812 handleEditorContainer->insertWidget(index, editor); 0813 handleEditorContainer->setCurrentIndex(index); 0814 }); 0815 0816 dialog->show(); 0817 dialog->raise(); 0818 dialog->activateWindow(); 0819 }