File indexing completed on 2024-06-16 04:16:47

0001 /*
0002  * KDE. Krita Project.
0003  *
0004  * SPDX-FileCopyrightText: 2020 Deif Lou <ginoba@gmail.com>
0005  * SPDX-FileCopyrightText: 2021 L. E. Segovia <amy@amyspark.me>
0006  *
0007  * SPDX-License-Identifier: GPL-2.0-or-later
0008  */
0009 
0010 #include <QStringList>
0011 
0012 #include <filter/kis_filter_configuration.h>
0013 #include <KisGlobalResourcesInterface.h>
0014 #include <kis_signals_blocker.h>
0015 #include <kis_gradient_painter.h>
0016 #include <KisViewManager.h>
0017 #include <kis_canvas_resource_provider.h>
0018 
0019 #include "KisGradientGeneratorConfiguration.h"
0020 #include "KisGradientGeneratorConfigWidget.h"
0021 
0022 KisGradientGeneratorConfigWidget::KisGradientGeneratorConfigWidget(QWidget* parent)
0023     : KisConfigWidget(parent)
0024     , m_view(nullptr)
0025 {
0026     QStringList shapeNames =
0027         QStringList()
0028         << i18nc("the gradient will be drawn linearly", "Linear")
0029         << i18nc("the gradient will be drawn bilinearly", "Bi-Linear")
0030         << i18nc("the gradient will be drawn radially", "Radial")
0031         << i18nc("the gradient will be drawn in a square around a centre", "Square")
0032         << i18nc("the gradient will be drawn as an asymmetric cone", "Conical")
0033         << i18nc("the gradient will be drawn as a symmetric cone", "Conical Symmetric")
0034         << i18nc("the gradient will be drawn as a spiral", "Spiral")
0035         << i18nc("the gradient will be drawn as a reverse spiral", "Reverse Spiral")
0036         << i18nc("the gradient will be drawn in a selection outline", "Shaped");
0037     QStringList repeatNames =
0038         QStringList()
0039         << i18nc("The gradient will not repeat", "None")
0040         << i18nc("The gradient will repeat forwards", "Forwards")
0041         << i18nc("The gradient will repeat alternatingly", "Alternating");
0042     QStringList spatialUnitsNames =
0043         QStringList()
0044         << i18nc("The position will be set in pixels", "Pixels")
0045         << i18nc("The position will be a percentage of the width", "Percent of the Width")
0046         << i18nc("The position will be a percentage of the height", "Percent of the Height")
0047         << i18nc("The position will be a percentage of the longest image side", "Percent of the Longest Side")
0048         << i18nc("The position will be a percentage of the shortest image side", "Percent of the Shortest Side");
0049     QStringList positioningNames =
0050         QStringList()
0051         << i18nc("The position will be relative to the top-left corner of the image", "Absolute")
0052         << i18nc("The position will be relative to the start point", "Relative");
0053 
0054     m_ui.setupUi(this);
0055 
0056     m_ui.comboBoxShape->addItems(shapeNames);
0057     m_ui.comboBoxRepeat->addItems(repeatNames);
0058     m_ui.sliderAntiAliasThreshold->setRange(0, 1, 3);
0059 
0060     m_ui.comboBoxStartPositionXUnits->addItems(spatialUnitsNames);
0061     m_ui.comboBoxStartPositionYUnits->addItems(spatialUnitsNames);
0062     m_ui.comboBoxEndPositionXUnits->addItems(spatialUnitsNames);
0063     m_ui.comboBoxEndPositionYUnits->addItems(spatialUnitsNames);
0064     m_ui.comboBoxEndPositionXPositioning->addItems(positioningNames);
0065     m_ui.comboBoxEndPositionYPositioning->addItems(positioningNames);
0066     m_ui.comboBoxEndPositionDistanceUnits->addItems(spatialUnitsNames);
0067 
0068     m_ui.widgetGradientEditor->setContentsMargins(10, 10, 10, 10);
0069     m_ui.widgetGradientEditor->loadUISettings();
0070 
0071     connect(m_ui.comboBoxShape, SIGNAL(currentIndexChanged(int)), this, SIGNAL(sigConfigurationUpdated()));
0072     connect(m_ui.comboBoxRepeat, SIGNAL(currentIndexChanged(int)), this, SIGNAL(sigConfigurationUpdated()));
0073     connect(m_ui.sliderAntiAliasThreshold, SIGNAL(valueChanged(qreal)), this, SIGNAL(sigConfigurationUpdated()));
0074     connect(m_ui.checkBoxDither, SIGNAL(toggled(bool)), this, SIGNAL(sigConfigurationUpdated()));
0075     connect(m_ui.checkBoxReverse, SIGNAL(toggled(bool)), this, SIGNAL(sigConfigurationUpdated()));
0076 
0077     connect(m_ui.spinBoxStartPositionX, SIGNAL(valueChanged(double)), this, SIGNAL(sigConfigurationUpdated()));
0078     connect(m_ui.spinBoxStartPositionY, SIGNAL(valueChanged(double)), this, SIGNAL(sigConfigurationUpdated()));
0079     connect(m_ui.comboBoxStartPositionXUnits, SIGNAL(currentIndexChanged(int)), this, SIGNAL(sigConfigurationUpdated()));
0080     connect(m_ui.comboBoxStartPositionYUnits, SIGNAL(currentIndexChanged(int)), this, SIGNAL(sigConfigurationUpdated()));
0081 
0082     connect(
0083         m_ui.radioButtonEndPositionCartesianCoordinates,
0084         SIGNAL(toggled(bool)),
0085         this,
0086         SLOT(slot_radioButtonEndPositionCartesianCoordinates_toggled(bool))
0087     );
0088     connect(
0089         m_ui.radioButtonEndPositionPolarCoordinates,
0090         SIGNAL(toggled(bool)),
0091         this,
0092         SLOT(slot_radioButtonEndPositionPolarCoordinates_toggled(bool))
0093     );
0094     connect(m_ui.spinBoxEndPositionX, SIGNAL(valueChanged(double)), this, SIGNAL(sigConfigurationUpdated()));
0095     connect(m_ui.spinBoxEndPositionY, SIGNAL(valueChanged(double)), this, SIGNAL(sigConfigurationUpdated()));
0096     connect(m_ui.comboBoxEndPositionXUnits, SIGNAL(currentIndexChanged(int)), this, SIGNAL(sigConfigurationUpdated()));
0097     connect(m_ui.comboBoxEndPositionYUnits, SIGNAL(currentIndexChanged(int)), this, SIGNAL(sigConfigurationUpdated()));
0098     connect(m_ui.comboBoxEndPositionXPositioning, SIGNAL(currentIndexChanged(int)), this, SIGNAL(sigConfigurationUpdated()));
0099     connect(m_ui.comboBoxEndPositionYPositioning, SIGNAL(currentIndexChanged(int)), this, SIGNAL(sigConfigurationUpdated()));
0100     connect(m_ui.angleSelectorEndPositionAngle, SIGNAL(angleChanged(qreal)), this, SIGNAL(sigConfigurationUpdated()));
0101     connect(m_ui.spinBoxEndPositionDistance, SIGNAL(valueChanged(double)), this, SIGNAL(sigConfigurationUpdated()));
0102     connect(m_ui.comboBoxEndPositionDistanceUnits, SIGNAL(currentIndexChanged(int)), this, SIGNAL(sigConfigurationUpdated()));
0103 
0104     connect(m_ui.widgetGradientEditor, SIGNAL(sigGradientChanged()), this, SIGNAL(sigConfigurationUpdated()));
0105 }
0106 
0107 KisGradientGeneratorConfigWidget::~KisGradientGeneratorConfigWidget()
0108 {
0109     m_ui.widgetGradientEditor->saveUISettings();
0110 }
0111 
0112 void KisGradientGeneratorConfigWidget::setConfiguration(const KisPropertiesConfigurationSP config)
0113 {
0114     const KisGradientGeneratorConfiguration *generatorConfig =
0115         dynamic_cast<const KisGradientGeneratorConfiguration*>(config.data());
0116     KIS_ASSERT(generatorConfig);
0117 
0118     {
0119         KisSignalsBlocker signalsBlocker(this);
0120 
0121         m_ui.comboBoxShape->setCurrentIndex(generatorConfig->shape());
0122         m_ui.comboBoxRepeat->setCurrentIndex(generatorConfig->repeat());
0123         m_ui.sliderAntiAliasThreshold->setValue(generatorConfig->antiAliasThreshold());
0124         m_ui.checkBoxDither->setChecked(generatorConfig->dither());
0125         m_ui.checkBoxReverse->setChecked(generatorConfig->reverse());
0126 
0127         m_ui.spinBoxStartPositionX->setValue(generatorConfig->startPositionX());
0128         m_ui.spinBoxStartPositionY->setValue(generatorConfig->startPositionY());
0129         m_ui.comboBoxStartPositionXUnits->setCurrentIndex(generatorConfig->startPositionXUnits());
0130         m_ui.comboBoxStartPositionYUnits->setCurrentIndex(generatorConfig->startPositionYUnits());
0131         if (generatorConfig->endPositionCoordinateSystem() == KisGradientGeneratorConfiguration::CoordinateSystemCartesian) {
0132             m_ui.radioButtonEndPositionCartesianCoordinates->setChecked(true);
0133         } else {
0134             m_ui.radioButtonEndPositionPolarCoordinates->setChecked(true);
0135         }
0136         m_ui.spinBoxEndPositionX->setValue(generatorConfig->endPositionX());
0137         m_ui.spinBoxEndPositionY->setValue(generatorConfig->endPositionY());
0138         m_ui.comboBoxEndPositionXUnits->setCurrentIndex(generatorConfig->endPositionXUnits());
0139         m_ui.comboBoxEndPositionYUnits->setCurrentIndex(generatorConfig->endPositionYUnits());
0140         m_ui.comboBoxEndPositionXPositioning->setCurrentIndex(generatorConfig->endPositionXPositioning());
0141         m_ui.comboBoxEndPositionYPositioning->setCurrentIndex(generatorConfig->endPositionYPositioning());
0142         m_ui.angleSelectorEndPositionAngle->setAngle(generatorConfig->endPositionAngle());
0143         m_ui.spinBoxEndPositionDistance->setValue(generatorConfig->endPositionDistance());
0144         m_ui.comboBoxEndPositionDistanceUnits->setCurrentIndex(generatorConfig->endPositionDistanceUnits());
0145 
0146         KoAbstractGradientSP fallbackGradient = nullptr;
0147         if (m_view) {
0148             KoCanvasResourcesInterfaceSP canvasResourcesInterface = m_view->canvasResourceProvider()->resourceManager()->canvasResourcesInterface();
0149             if (canvasResourcesInterface) {
0150                 KoAbstractGradientSP currentGradient =
0151                     canvasResourcesInterface->resource(KoCanvasResource::CurrentGradient).value<KoAbstractGradientSP>();
0152                 if (currentGradient) {
0153                     fallbackGradient = currentGradient->clone().dynamicCast<KoAbstractGradient>();
0154                 }
0155             }
0156         }
0157         m_ui.widgetGradientEditor->setGradient(generatorConfig->gradient(fallbackGradient));
0158     }
0159 
0160     emit sigConfigurationItemChanged();
0161 }
0162 
0163 KisPropertiesConfigurationSP KisGradientGeneratorConfigWidget::configuration() const
0164 {
0165     KisGradientGeneratorConfiguration *config = new KisGradientGeneratorConfiguration(KisGlobalResourcesInterface::instance());
0166 
0167     config->setShape(static_cast<KisGradientPainter::enumGradientShape>(m_ui.comboBoxShape->currentIndex()));
0168     config->setRepeat(static_cast<KisGradientPainter::enumGradientRepeat>(m_ui.comboBoxRepeat->currentIndex()));
0169     config->setAntiAliasThreshold(m_ui.sliderAntiAliasThreshold->value());
0170     config->setDither(m_ui.checkBoxDither->isChecked());
0171     config->setReverse(m_ui.checkBoxReverse->isChecked());
0172 
0173     config->setStartPositionX(m_ui.spinBoxStartPositionX->value());
0174     config->setStartPositionY(m_ui.spinBoxStartPositionY->value());
0175     config->setStartPositionXUnits(static_cast<KisGradientGeneratorConfiguration::SpatialUnits>(m_ui.comboBoxStartPositionXUnits->currentIndex()));
0176     config->setStartPositionYUnits(static_cast<KisGradientGeneratorConfiguration::SpatialUnits>(m_ui.comboBoxStartPositionYUnits->currentIndex()));
0177     if (m_ui.radioButtonEndPositionCartesianCoordinates->isChecked()) {
0178         config->setEndPositionCoordinateSystem(KisGradientGeneratorConfiguration::CoordinateSystemCartesian);
0179     } else {
0180         config->setEndPositionCoordinateSystem(KisGradientGeneratorConfiguration::CoordinateSystemPolar);
0181     }
0182     config->setEndPositionX(m_ui.spinBoxEndPositionX->value());
0183     config->setEndPositionY(m_ui.spinBoxEndPositionY->value());
0184     config->setEndPositionXUnits(static_cast<KisGradientGeneratorConfiguration::SpatialUnits>(m_ui.comboBoxEndPositionXUnits->currentIndex()));
0185     config->setEndPositionYUnits(static_cast<KisGradientGeneratorConfiguration::SpatialUnits>(m_ui.comboBoxEndPositionYUnits->currentIndex()));
0186     config->setEndPositionXPositioning(static_cast<KisGradientGeneratorConfiguration::Positioning>(m_ui.comboBoxEndPositionXPositioning->currentIndex()));
0187     config->setEndPositionYPositioning(static_cast<KisGradientGeneratorConfiguration::Positioning>(m_ui.comboBoxEndPositionYPositioning->currentIndex()));
0188     config->setEndPositionAngle(m_ui.angleSelectorEndPositionAngle->angle());
0189     config->setEndPositionDistance(m_ui.spinBoxEndPositionDistance->value());
0190     config->setEndPositionDistanceUnits(static_cast<KisGradientGeneratorConfiguration::SpatialUnits>(m_ui.comboBoxEndPositionDistanceUnits->currentIndex()));
0191 
0192     KoAbstractGradientSP gradient = m_ui.widgetGradientEditor->gradient();
0193     if (gradient && m_view) {
0194         KoCanvasResourcesInterfaceSP canvasResourcesInterface =
0195             m_view->canvasResourceProvider()->resourceManager()->canvasResourcesInterface();
0196         gradient->bakeVariableColors(canvasResourcesInterface);
0197     }
0198     config->setGradient(gradient);
0199 
0200     return config;
0201 }
0202 
0203 void KisGradientGeneratorConfigWidget::setView(KisViewManager *view)
0204 {
0205     m_view = view;
0206 
0207     KoCanvasResourcesInterfaceSP canvasResourcesInterface = view ? view->canvasResourceProvider()->resourceManager()->canvasResourcesInterface() : nullptr;
0208     setCanvasResourcesInterface(canvasResourcesInterface);
0209 }
0210 
0211 void KisGradientGeneratorConfigWidget::setCanvasResourcesInterface(KoCanvasResourcesInterfaceSP canvasResourcesInterface)
0212 {
0213     m_ui.widgetGradientEditor->setCanvasResourcesInterface(canvasResourcesInterface);
0214     KisConfigWidget::setCanvasResourcesInterface(canvasResourcesInterface);
0215 }
0216 
0217 void KisGradientGeneratorConfigWidget::slot_radioButtonEndPositionCartesianCoordinates_toggled(bool enabled)
0218 {
0219     if (!enabled) {
0220         return;
0221     }
0222 
0223     m_ui.stackedWidgetEndPosition->setCurrentIndex(0);
0224     emit sigConfigurationItemChanged();
0225 }
0226 
0227 void KisGradientGeneratorConfigWidget::slot_radioButtonEndPositionPolarCoordinates_toggled(bool enabled)
0228 {
0229     if (!enabled) {
0230         return;
0231     }
0232 
0233     m_ui.stackedWidgetEndPosition->setCurrentIndex(1);
0234     emit sigConfigurationItemChanged();
0235 }