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

0001 /*
0002  * KDE. Krita Project.
0003  *
0004  * SPDX-FileCopyrightText: 2020 Deif Lou <ginoba@gmail.com>
0005  *
0006  * SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #include <KoColor.h>
0010 #include <filter/kis_filter_configuration.h>
0011 #include <KisGlobalResourcesInterface.h>
0012 #include <kis_signals_blocker.h>
0013 #include <kis_generator_registry.h>
0014 #include <KisViewManager.h>
0015 #include <kis_canvas_resource_provider.h>
0016 #include <KisSpinBoxI18nHelper.h>
0017 #include <KoUnit.h>
0018 
0019 #include "KisScreentoneConfigWidget.h"
0020 #include "KisScreentoneScreentoneFunctions.h"
0021 #include "KisScreentoneGeneratorConfiguration.h"
0022 
0023 KisScreentoneConfigWidget::KisScreentoneConfigWidget(QWidget* parent, const KoColorSpace *cs)
0024     : KisConfigWidget(parent)
0025     , m_view(nullptr)
0026     , m_colorSpace(cs)
0027 {
0028     m_ui.setupUi(this);
0029 
0030     setupPatternComboBox();
0031     setupShapeComboBox();
0032     setupInterpolationComboBox();
0033     m_ui.buttonEqualizationNone->setGroupPosition(KoGroupButton::GroupLeft);
0034     m_ui.buttonEqualizationFunctionBased->setGroupPosition(KoGroupButton::GroupCenter);
0035     m_ui.buttonEqualizationTemplateBased->setGroupPosition(KoGroupButton::GroupRight);
0036 
0037     m_ui.sliderForegroundOpacity->setRange(0, 100);
0038     KisSpinBoxI18nHelper::setText(m_ui.sliderForegroundOpacity,
0039                                   i18nc("{n} is the number value, % is the percent sign", "Opacity: {n}%"));
0040     m_ui.sliderBackgroundOpacity->setRange(0, 100);
0041     KisSpinBoxI18nHelper::setText(m_ui.sliderBackgroundOpacity,
0042                                   i18nc("{n} is the number value, % is the percent sign", "Opacity: {n}%"));
0043     m_ui.sliderBrightness->setRange(0.0, 100.0, 2);
0044     m_ui.sliderBrightness->setSingleStep(1.0);
0045     KisSpinBoxI18nHelper::setText(m_ui.sliderBrightness,
0046                                   i18nc("{n} is the number value, % is the percent sign", "{n}%"));
0047     m_ui.sliderContrast->setRange(0.0, 100.0, 2);
0048     m_ui.sliderContrast->setSingleStep(1.0);
0049     KisSpinBoxI18nHelper::setText(m_ui.sliderContrast, i18nc("{n} is the number value, % is the percent sign", "{n}%"));
0050 
0051     m_ui.buttonSizeModeResolutionBased->setGroupPosition(KoGroupButton::GroupLeft);
0052     m_ui.buttonSizeModePixelBased->setGroupPosition(KoGroupButton::GroupRight);
0053     m_ui.sliderResolution->setRange(1.0, 9999.0, 2);
0054     m_ui.sliderResolution->setSoftRange(72.0, 600.0);
0055     m_ui.sliderFrequencyX->setPrefix(i18n("X: "));
0056     m_ui.sliderFrequencyX->setSingleStep(1.0);
0057     m_ui.sliderFrequencyY->setPrefix(i18n("Y: "));
0058     m_ui.sliderFrequencyY->setSingleStep(1.0);
0059     slot_setFrequencySlidersRanges();
0060     slot_comboBoxUnits_currentIndexChanged(0);
0061     m_ui.sliderPositionX->setRange(-1000.0, 1000.0, 2);
0062     m_ui.sliderPositionX->setSoftRange(-100.0, 100.0);
0063     m_ui.sliderPositionX->setPrefix(i18n("X: "));
0064     m_ui.sliderPositionX->setSuffix(i18n(" px"));
0065     m_ui.sliderPositionX->setSingleStep(1.0);
0066     m_ui.sliderPositionY->setRange(-1000.0, 1000.0, 2);
0067     m_ui.sliderPositionY->setSoftRange(-100.0, 100.0);
0068     m_ui.sliderPositionY->setPrefix(i18n("Y: "));
0069     m_ui.sliderPositionY->setSuffix(i18n(" px"));
0070     m_ui.sliderPositionY->setSingleStep(1.0);
0071     m_ui.sliderSizeX->setRange(1.0, 1000.0, 2);
0072     m_ui.sliderSizeX->setSoftRange(1.0, 100.0);
0073     m_ui.sliderSizeX->setPrefix(i18n("X: "));
0074     m_ui.sliderSizeX->setSuffix(i18n(" px"));
0075     m_ui.sliderSizeX->setSingleStep(1.0);
0076     m_ui.sliderSizeX->setExponentRatio(4.32);
0077     m_ui.sliderSizeY->setRange(1.0, 1000.0, 2);
0078     m_ui.sliderSizeY->setSoftRange(1.0, 100.0);
0079     m_ui.sliderSizeY->setPrefix(i18n("Y: "));
0080     m_ui.sliderSizeY->setSuffix(i18n(" px"));
0081     m_ui.sliderSizeY->setSingleStep(1.0);
0082     m_ui.sliderSizeY->setExponentRatio(4.32);
0083     m_ui.sliderShearX->setRange(-10.0, 10.0, 2);
0084     m_ui.sliderShearX->setSoftRange(-2.0, 2.0);
0085     m_ui.sliderShearX->setPrefix(i18n("X: "));
0086     m_ui.sliderShearX->setSingleStep(0.1);
0087     m_ui.sliderShearY->setRange(-10.0, 10.0, 2);
0088     m_ui.sliderShearY->setSoftRange(-2.0, 2.0);
0089     m_ui.sliderShearY->setPrefix(i18n("Y: "));
0090     m_ui.sliderShearY->setSingleStep(0.1);
0091     m_ui.sliderAlignToPixelGridX->setRange(1, 20);
0092     m_ui.sliderAlignToPixelGridY->setRange(1, 20);
0093     KisSpinBoxI18nHelper::install(m_ui.sliderAlignToPixelGridX, [](int value) {
0094         // i18n: This is meant to be used in a spinbox so keep the {n} in the text
0095         //       and it will be substituted by the number. The text before will be
0096         //       used as the prefix and the text after as the suffix
0097         return i18ncp("Horizontal pixel grid alignment prefix/suffix for spinboxes in screentone generator", "Every {n} cell horizontally", "Every {n} cells horizontally", value);
0098     });
0099     KisSpinBoxI18nHelper::install(m_ui.sliderAlignToPixelGridY, [](int value) {
0100         // i18n: This is meant to be used in a spinbox so keep the {n} in the text
0101         //       and it will be substituted by the number. The text before will be
0102         //       used as the prefix and the text after as the suffix
0103         return i18ncp("Vertical pixel grid alignment prefix/suffix for spinboxes in screentone generator", "Every {n} cell vertically", "Every {n} cells vertically", value);
0104     });
0105     slot_buttonSizeModeResolutionBased_toggled(true);
0106 
0107     connect(m_ui.comboBoxPattern, SIGNAL(currentIndexChanged(int)), this, SLOT(slot_comboBoxPattern_currentIndexChanged(int)));
0108     connect(m_ui.comboBoxShape, SIGNAL(currentIndexChanged(int)), this, SLOT(slot_comboBoxShape_currentIndexChanged(int)));
0109     connect(m_ui.comboBoxInterpolation, SIGNAL(currentIndexChanged(int)), this, SIGNAL(sigConfigurationUpdated()));
0110     connect(m_ui.buttonEqualizationNone, SIGNAL(toggled(bool)), this, SIGNAL(sigConfigurationUpdated()));
0111     connect(m_ui.buttonEqualizationFunctionBased, SIGNAL(toggled(bool)), this, SIGNAL(sigConfigurationUpdated()));
0112     connect(m_ui.buttonEqualizationTemplateBased, SIGNAL(toggled(bool)), this, SIGNAL(sigConfigurationUpdated()));
0113     
0114     connect(m_ui.buttonForegroundColor, SIGNAL(changed(const KoColor&)), this, SIGNAL(sigConfigurationUpdated()));
0115     connect(m_ui.sliderForegroundOpacity, SIGNAL(valueChanged(int)), this, SIGNAL(sigConfigurationUpdated()));
0116     connect(m_ui.buttonBackgroundColor, SIGNAL(changed(const KoColor&)), this, SIGNAL(sigConfigurationUpdated()));
0117     connect(m_ui.sliderBackgroundOpacity, SIGNAL(valueChanged(int)), this, SIGNAL(sigConfigurationUpdated()));
0118     connect(m_ui.checkBoxInvert, SIGNAL(toggled(bool)), this, SIGNAL(sigConfigurationUpdated()));
0119     connect(m_ui.sliderBrightness, SIGNAL(valueChanged(qreal)), this, SIGNAL(sigConfigurationUpdated()));
0120     connect(m_ui.sliderContrast, SIGNAL(valueChanged(qreal)), this, SIGNAL(sigConfigurationUpdated()));
0121     
0122     connect(m_ui.buttonSizeModeResolutionBased, SIGNAL(toggled(bool)), this, SLOT(slot_buttonSizeModeResolutionBased_toggled(bool)));
0123     connect(m_ui.buttonSizeModePixelBased, SIGNAL(toggled(bool)), this, SLOT(slot_buttonSizeModePixelBased_toggled(bool)));
0124     connect(m_ui.comboBoxUnits, SIGNAL(currentIndexChanged(int)), this, SLOT(slot_comboBoxUnits_currentIndexChanged(int)));
0125     connect(m_ui.sliderResolution, SIGNAL(valueChanged(qreal)), this, SLOT(slot_sliderResolution_valueChanged(qreal)));
0126     connect(m_ui.sliderResolution, SIGNAL(valueChanged(qreal)), this, SIGNAL(sigConfigurationUpdated()));
0127     connect(m_ui.buttonResolutionFromImage, SIGNAL(clicked()), this, SLOT(slot_buttonResolutionFromImage_clicked()));
0128     connect(m_ui.sliderFrequencyX, SIGNAL(valueChanged(qreal)), this, SLOT(slot_sliderFrequencyX_valueChanged(qreal)));
0129     connect(m_ui.sliderFrequencyY, SIGNAL(valueChanged(qreal)), this, SLOT(slot_sliderFrequencyY_valueChanged(qreal)));
0130     connect(m_ui.buttonConstrainFrequency, SIGNAL(keepAspectRatioChanged(bool)), this, SLOT(slot_buttonConstrainFrequency_keepAspectRatioChanged(bool)));
0131     connect(m_ui.sliderPositionX, SIGNAL(valueChanged(qreal)), this, SIGNAL(sigConfigurationUpdated()));
0132     connect(m_ui.sliderPositionY, SIGNAL(valueChanged(qreal)), this, SIGNAL(sigConfigurationUpdated()));
0133     connect(m_ui.sliderSizeX, SIGNAL(valueChanged(qreal)), this, SLOT(slot_sliderSizeX_valueChanged(qreal)));
0134     connect(m_ui.sliderSizeY, SIGNAL(valueChanged(qreal)), this, SLOT(slot_sliderSizeY_valueChanged(qreal)));
0135     connect(m_ui.buttonConstrainSize, SIGNAL(keepAspectRatioChanged(bool)), this, SLOT(slot_buttonConstrainSize_keepAspectRatioChanged(bool)));
0136     connect(m_ui.sliderShearX, SIGNAL(valueChanged(qreal)), this, SIGNAL(sigConfigurationUpdated()));
0137     connect(m_ui.sliderShearY, SIGNAL(valueChanged(qreal)), this, SIGNAL(sigConfigurationUpdated()));
0138     connect(m_ui.angleSelectorRotation, SIGNAL(angleChanged(qreal)), this, SIGNAL(sigConfigurationUpdated()));
0139     connect(m_ui.checkBoxAlignToPixelGrid, SIGNAL(toggled(bool)), this, SIGNAL(sigConfigurationUpdated()));
0140     connect(m_ui.sliderAlignToPixelGridX, SIGNAL(valueChanged(int)), this, SLOT(slot_sliderAlignToPixelGridX_valueChanged(int)));
0141     connect(m_ui.sliderAlignToPixelGridY, SIGNAL(valueChanged(int)), this, SLOT(slot_sliderAlignToPixelGridY_valueChanged(int)));
0142 }
0143 
0144 KisScreentoneConfigWidget::~KisScreentoneConfigWidget()
0145 {}
0146 
0147 void KisScreentoneConfigWidget::setConfiguration(const KisPropertiesConfigurationSP config)
0148 {
0149     const KisScreentoneGeneratorConfiguration *generatorConfig =
0150         dynamic_cast<const KisScreentoneGeneratorConfiguration*>(config.data());
0151     KIS_ASSERT(generatorConfig);
0152         
0153     {
0154         KisSignalsBlocker blocker1(m_ui.buttonSizeModeResolutionBased, m_ui.buttonSizeModePixelBased,
0155                                    m_ui.sliderResolution, m_ui.buttonConstrainFrequency,
0156                                    m_ui.sliderFrequencyX, m_ui.sliderFrequencyY);
0157         KisSignalsBlocker blocker2(m_ui.sliderSizeX, m_ui.sliderSizeY,
0158                                    m_ui.buttonConstrainSize, m_ui.sliderAlignToPixelGridX,
0159                                    m_ui.sliderAlignToPixelGridY, this);
0160 
0161         m_ui.comboBoxPattern->setCurrentIndex(generatorConfig->pattern());
0162         m_ui.comboBoxShape->setCurrentIndex(shapeToComboIndex(generatorConfig->pattern(), generatorConfig->shape()));
0163         m_ui.comboBoxInterpolation->setCurrentIndex(generatorConfig->interpolation());
0164         const int equalizationMode = generatorConfig->equalizationMode();
0165         if (equalizationMode == KisScreentoneEqualizationMode_FunctionBased) {
0166             m_ui.buttonEqualizationFunctionBased->setChecked(true);
0167         } else if (equalizationMode == KisScreentoneEqualizationMode_TemplateBased) {
0168             m_ui.buttonEqualizationTemplateBased->setChecked(true);
0169         } else {
0170             m_ui.buttonEqualizationNone->setChecked(true);
0171         }
0172 
0173         KoColor c;
0174         c = generatorConfig->foregroundColor();
0175         c.convertTo(m_colorSpace);
0176         c.setOpacity(1.0);
0177         m_ui.buttonForegroundColor->setColor(c);
0178         m_ui.sliderForegroundOpacity->setValue(generatorConfig->foregroundOpacity());
0179         c = generatorConfig->backgroundColor();
0180         c.convertTo(m_colorSpace);
0181         c.setOpacity(1.0);
0182         m_ui.buttonBackgroundColor->setColor(c);
0183         m_ui.sliderBackgroundOpacity->setValue(generatorConfig->backgroundOpacity());
0184         m_ui.checkBoxInvert->setChecked(generatorConfig->invert());
0185         m_ui.sliderBrightness->setValue(generatorConfig->brightness());
0186         m_ui.sliderContrast->setValue(generatorConfig->contrast());
0187 
0188         m_ui.comboBoxUnits->setCurrentIndex(generatorConfig->units());
0189         m_ui.sliderResolution->setValue(generatorConfig->resolution());
0190         slot_setFrequencySlidersRanges();
0191         m_ui.buttonConstrainFrequency->setKeepAspectRatio(generatorConfig->constrainFrequency());
0192         m_ui.sliderFrequencyX->setValue(generatorConfig->frequencyX());
0193         // Set the frequency y slider to the frequency y value only if the frequency is not constrained
0194         if (m_ui.buttonConstrainFrequency->keepAspectRatio()) {
0195             m_ui.sliderFrequencyY->setValue(generatorConfig->frequencyX());
0196         } else {
0197             m_ui.sliderFrequencyY->setValue(generatorConfig->frequencyY());
0198         }
0199         m_ui.sliderPositionX->setValue(generatorConfig->positionX());
0200         m_ui.sliderPositionY->setValue(generatorConfig->positionY());
0201         m_ui.buttonConstrainSize->setKeepAspectRatio(generatorConfig->constrainSize());
0202         m_ui.sliderSizeX->setValue(generatorConfig->sizeX());
0203         // Set the size y slider to the sithe y value only if the size must not be squared
0204         if (m_ui.buttonConstrainSize->keepAspectRatio()) {
0205             m_ui.sliderSizeY->setValue(generatorConfig->sizeX());
0206         } else {
0207             m_ui.sliderSizeY->setValue(generatorConfig->sizeY());
0208         }
0209         m_ui.sliderShearX->setValue(generatorConfig->shearX());
0210         m_ui.sliderShearY->setValue(generatorConfig->shearY());
0211         m_ui.angleSelectorRotation->setAngle(generatorConfig->rotation());
0212         m_ui.checkBoxAlignToPixelGrid->setChecked(generatorConfig->alignToPixelGrid());
0213         m_ui.sliderAlignToPixelGridX->setValue(generatorConfig->alignToPixelGridX());
0214         m_ui.sliderAlignToPixelGridY->setValue(generatorConfig->alignToPixelGridY());
0215         KisSpinBoxI18nHelper::update(m_ui.sliderAlignToPixelGridX);
0216         KisSpinBoxI18nHelper::update(m_ui.sliderAlignToPixelGridY);
0217 
0218         if (generatorConfig->sizeMode() == KisScreentoneSizeMode_PixelBased) {
0219             m_ui.buttonSizeModePixelBased->setChecked(true);
0220             slot_setFrequencyFromSize();
0221             slot_buttonSizeModePixelBased_toggled(true);
0222         } else {
0223             m_ui.buttonSizeModeResolutionBased->setChecked(true);
0224             slot_setSizeFromFrequency();
0225             slot_buttonSizeModeResolutionBased_toggled(true);
0226         }
0227     }
0228     emit sigConfigurationItemChanged();
0229 }
0230 
0231 KisPropertiesConfigurationSP KisScreentoneConfigWidget::configuration() const
0232 {
0233     KisGeneratorSP generator = KisGeneratorRegistry::instance()->get(KisScreentoneGeneratorConfiguration::defaultName());
0234     KisScreentoneGeneratorConfigurationSP config =
0235         dynamic_cast<KisScreentoneGeneratorConfiguration*>(
0236             generator->factoryConfiguration(KisGlobalResourcesInterface::instance()).data()
0237         );
0238         
0239     config->setPattern(m_ui.comboBoxPattern->currentIndex());
0240     config->setShape(comboIndexToShape(m_ui.comboBoxPattern->currentIndex(), m_ui.comboBoxShape->currentIndex()));
0241     config->setInterpolation(m_ui.comboBoxInterpolation->currentIndex());
0242     if (m_ui.buttonEqualizationFunctionBased->isChecked()) {
0243         config->setEqualizationMode(KisScreentoneEqualizationMode_FunctionBased);
0244     } else if (m_ui.buttonEqualizationTemplateBased->isChecked()) {
0245         config->setEqualizationMode(KisScreentoneEqualizationMode_TemplateBased);
0246     } else {
0247         config->setEqualizationMode(KisScreentoneEqualizationMode_None);
0248     }
0249 
0250     config->setForegroundColor(m_ui.buttonForegroundColor->color());
0251     config->setForegroundOpacity(m_ui.sliderForegroundOpacity->value());
0252     config->setBackgroundColor(m_ui.buttonBackgroundColor->color());
0253     config->setBackgroundOpacity(m_ui.sliderBackgroundOpacity->value());
0254     config->setInvert(m_ui.checkBoxInvert->isChecked());
0255     config->setBrightness(m_ui.sliderBrightness->value());
0256     config->setContrast(m_ui.sliderContrast->value());
0257 
0258     config->setSizeMode(m_ui.buttonSizeModePixelBased->isChecked() ? KisScreentoneSizeMode_PixelBased
0259                                                                    : KisScreentoneSizeMode_ResolutionBased);
0260     config->setUnits(m_ui.comboBoxUnits->currentIndex());
0261     config->setResolution(m_ui.sliderResolution->value());
0262     config->setFrequencyX(m_ui.sliderFrequencyX->value());
0263     config->setFrequencyY(m_ui.sliderFrequencyY->value());
0264     config->setConstrainFrequency(m_ui.buttonConstrainFrequency->keepAspectRatio());
0265     config->setPositionX(m_ui.sliderPositionX->value());
0266     config->setPositionY(m_ui.sliderPositionY->value());
0267     config->setSizeX(m_ui.sliderSizeX->value());
0268     config->setSizeY(m_ui.sliderSizeY->value());
0269     config->setConstrainSize(m_ui.buttonConstrainSize->keepAspectRatio());
0270     config->setShearX(m_ui.sliderShearX->value());
0271     config->setShearY(m_ui.sliderShearY->value());
0272     config->setRotation(m_ui.angleSelectorRotation->angle());
0273     config->setAlignToPixelGrid(m_ui.checkBoxAlignToPixelGrid->isChecked());
0274     config->setAlignToPixelGridX(m_ui.sliderAlignToPixelGridX->value());
0275     config->setAlignToPixelGridY(m_ui.sliderAlignToPixelGridY->value());
0276 
0277     return config;
0278 }
0279 
0280 void KisScreentoneConfigWidget::setView(KisViewManager *view)
0281 {
0282     m_view = view;
0283     m_ui.buttonResolutionFromImage->setEnabled(true);
0284 
0285     KoCanvasResourcesInterfaceSP canvasResourcesInterface = view ? view->canvasResourceProvider()->resourceManager()->canvasResourcesInterface() : nullptr;
0286     setCanvasResourcesInterface(canvasResourcesInterface);
0287 }
0288 
0289 void KisScreentoneConfigWidget::setupPatternComboBox()
0290 {
0291     m_ui.comboBoxPattern->clear();
0292     m_ui.comboBoxPattern->addItems(screentonePatternNames());
0293 }
0294 
0295 void KisScreentoneConfigWidget::setupShapeComboBox()
0296 {
0297     m_ui.comboBoxShape->clear();
0298     QStringList names = screentoneShapeNames(m_ui.comboBoxPattern->currentIndex());
0299     if (names.isEmpty()) {
0300         m_ui.labelShape->hide();
0301         m_ui.comboBoxShape->hide();
0302     } else {
0303         m_ui.comboBoxShape->addItems(names);
0304         m_ui.labelShape->show();
0305         m_ui.comboBoxShape->show();
0306     }
0307 }
0308 
0309 void KisScreentoneConfigWidget::setupInterpolationComboBox()
0310 {
0311     if (m_ui.comboBoxInterpolation->count() > 0) {
0312         m_lastSelectedInterpolationText = m_ui.comboBoxInterpolation->currentText();
0313         m_ui.comboBoxInterpolation->clear();
0314     }
0315     QStringList names =
0316         screentoneInterpolationNames(
0317             m_ui.comboBoxPattern->currentIndex(),
0318             comboIndexToShape(m_ui.comboBoxPattern->currentIndex(), m_ui.comboBoxShape->currentIndex())
0319         );
0320     if (names.isEmpty()) {
0321         m_ui.labelInterpolation->hide();
0322         m_ui.comboBoxInterpolation->hide();
0323     } else {
0324         m_ui.comboBoxInterpolation->addItems(names);
0325         int i = m_ui.comboBoxInterpolation->findText(m_lastSelectedInterpolationText);
0326         m_ui.comboBoxInterpolation->setCurrentIndex(i != -1 ? i : KisScreentoneGeneratorConfiguration::defaultInterpolation());
0327         m_ui.labelInterpolation->show();
0328         m_ui.comboBoxInterpolation->show();
0329     }
0330 }
0331 
0332 int KisScreentoneConfigWidget::shapeToComboIndex(int pattern, int shape) const
0333 {
0334     if (pattern == KisScreentonePatternType_Lines) {
0335         return shape;
0336     }
0337     if (shape == KisScreentoneShapeType_RoundDots) {
0338         return 0;
0339     } else if (shape == KisScreentoneShapeType_EllipseDotsLegacy) {
0340         return 1;
0341     } else if (shape == KisScreentoneShapeType_EllipseDots) {
0342         return 2;
0343     } else if (shape == KisScreentoneShapeType_DiamondDots) {
0344         return 3;
0345     } else if (shape == KisScreentoneShapeType_SquareDots) {
0346         return 4;
0347     }
0348     return -1;
0349 }
0350 
0351 int KisScreentoneConfigWidget::comboIndexToShape(int patternIndex, int shapeIndex) const
0352 {
0353     if (patternIndex == KisScreentonePatternType_Lines) {
0354         return shapeIndex;
0355     }
0356     switch (shapeIndex) {
0357         case 0: return KisScreentoneShapeType_RoundDots;
0358         case 1: return KisScreentoneShapeType_EllipseDotsLegacy;
0359         case 2: return KisScreentoneShapeType_EllipseDots;
0360         case 3: return KisScreentoneShapeType_DiamondDots;
0361         case 4: return KisScreentoneShapeType_SquareDots;
0362     }
0363     return -1;
0364 }
0365 
0366 void KisScreentoneConfigWidget::slot_comboBoxPattern_currentIndexChanged(int)
0367 {
0368     KisSignalsBlocker blocker(m_ui.comboBoxShape, m_ui.comboBoxInterpolation);
0369     setupShapeComboBox();
0370     setupInterpolationComboBox();
0371     emit sigConfigurationItemChanged();
0372 }
0373 
0374 void KisScreentoneConfigWidget::slot_comboBoxShape_currentIndexChanged(int)
0375 {
0376     KisSignalsBlocker blocker(m_ui.comboBoxInterpolation);
0377     setupInterpolationComboBox();
0378     emit sigConfigurationItemChanged();
0379 }
0380 
0381 void KisScreentoneConfigWidget::slot_buttonSizeModeResolutionBased_toggled(bool checked)
0382 {
0383     if (!checked) {
0384         return;
0385     }
0386 
0387     m_ui.tabTransformation->setUpdatesEnabled(false);
0388 
0389     if (m_ui.layoutTransformation->indexOf(m_ui.containerSize) != -1) {
0390         m_ui.containerSize->hide();
0391         m_ui.labelSize->hide();
0392         m_ui.layoutTransformation->takeRow(m_ui.containerSize);
0393     }
0394 
0395     // Prevent adding the widgets if they are already in the layout
0396     if (m_ui.layoutTransformation->indexOf(m_ui.containerResolution) == -1) {
0397         m_ui.layoutTransformation->insertRow(1, m_ui.labelResolution, m_ui.containerResolution);
0398         m_ui.layoutTransformation->insertRow(2, m_ui.labelFrequency, m_ui.containerFrequency);
0399         m_ui.containerResolution->show();
0400         m_ui.containerFrequency->show();
0401         m_ui.labelResolution->show();
0402         m_ui.labelFrequency->show();
0403     }
0404 
0405     slot_setSizeFromFrequency();
0406 
0407     m_ui.tabTransformation->setUpdatesEnabled(true);
0408 
0409     emit sigConfigurationItemChanged();
0410 }
0411 
0412 void KisScreentoneConfigWidget::slot_buttonSizeModePixelBased_toggled(bool checked)
0413 {
0414     if (!checked) {
0415         return;
0416     }
0417 
0418     m_ui.tabTransformation->setUpdatesEnabled(false);
0419 
0420     if (m_ui.layoutTransformation->indexOf(m_ui.containerResolution) != -1) {
0421         m_ui.containerResolution->hide();
0422         m_ui.containerFrequency->hide();
0423         m_ui.labelResolution->hide();
0424         m_ui.labelFrequency->hide();
0425         m_ui.layoutTransformation->takeRow(m_ui.containerResolution);
0426         m_ui.layoutTransformation->takeRow(m_ui.containerFrequency);
0427     }
0428 
0429     // Prevent adding the widgets if they are already in the layout
0430     if (m_ui.layoutTransformation->indexOf(m_ui.containerSize) == -1) {
0431         m_ui.layoutTransformation->insertRow(1, m_ui.labelSize, m_ui.containerSize);
0432         m_ui.containerSize->show();
0433         m_ui.labelSize->show();
0434     }
0435 
0436     slot_setFrequencyFromSize();
0437 
0438     m_ui.tabTransformation->setUpdatesEnabled(true);
0439 
0440     emit sigConfigurationItemChanged();
0441 }
0442 
0443 void KisScreentoneConfigWidget::slot_comboBoxUnits_currentIndexChanged(int index)
0444 {
0445     const QString resSuffix =
0446         index == 0
0447         ? i18nc("Screentone generator resolution units - pixels/inch", " pixels/inch")
0448         : i18nc("Screentone generator resolution units - pixels/cm", " pixels/cm");
0449     const QString freqSuffix =
0450         index == 0
0451         ? i18nc("Screentone generator line units - lines/inch", " lines/inch")
0452         : i18nc("Screentone generator line units - lines/cm", " lines/cm");
0453     m_ui.sliderResolution->setSuffix(resSuffix);
0454     m_ui.sliderFrequencyX->setSuffix(freqSuffix);
0455     m_ui.sliderFrequencyY->setSuffix(freqSuffix);
0456     {
0457         KisSignalsBlocker blocker(m_ui.sliderResolution, m_ui.sliderFrequencyX, m_ui.sliderFrequencyY);
0458         const KoUnit unitFrom = index == 1 ? KoUnit(KoUnit::Centimeter) : KoUnit(KoUnit::Inch);
0459         const KoUnit unitTo = index == 1 ? KoUnit(KoUnit::Inch) : KoUnit(KoUnit::Centimeter);
0460         m_ui.sliderResolution->setValue(
0461             KoUnit::convertFromUnitToUnit(
0462                 m_ui.sliderResolution->value(), unitFrom, unitTo)
0463         );
0464         m_ui.sliderFrequencyX->setValue(
0465             KoUnit::convertFromUnitToUnit(m_ui.sliderFrequencyX->value(), unitFrom, unitTo)
0466         );
0467         m_ui.sliderFrequencyY->setValue(
0468             KoUnit::convertFromUnitToUnit(m_ui.sliderFrequencyY->value(), unitFrom, unitTo)
0469         );
0470     }
0471     emit sigConfigurationItemChanged();
0472 }
0473 
0474 void KisScreentoneConfigWidget::slot_buttonResolutionFromImage_clicked()
0475 {
0476     if (m_view) {
0477         if (m_ui.comboBoxUnits->currentIndex() == 1) {
0478             m_ui.sliderResolution->setValue(
0479                 KoUnit::convertFromUnitToUnit(m_view->image()->yRes(), KoUnit(KoUnit::Centimeter), KoUnit(KoUnit::Point))
0480             );
0481         } else {
0482             m_ui.sliderResolution->setValue(
0483                 KoUnit::convertFromUnitToUnit(m_view->image()->yRes(), KoUnit(KoUnit::Inch), KoUnit(KoUnit::Point))
0484             );
0485         }
0486     }
0487 }
0488 
0489 void KisScreentoneConfigWidget::slot_sliderResolution_valueChanged(qreal value)
0490 {
0491     Q_UNUSED(value);
0492     slot_setFrequencySlidersRanges();
0493     slot_setSizeFromFrequency();
0494     emit sigConfigurationItemChanged();
0495 }
0496 
0497 void KisScreentoneConfigWidget::slot_sliderFrequencyX_valueChanged(qreal value)
0498 {
0499     if (m_ui.buttonConstrainFrequency->keepAspectRatio()) {
0500         KisSignalsBlocker blocker(m_ui.sliderFrequencyY);
0501         m_ui.sliderFrequencyY->setValue(value);
0502     }
0503     slot_setSizeFromFrequency();
0504     emit sigConfigurationItemChanged();
0505 }
0506 
0507 void KisScreentoneConfigWidget::slot_sliderFrequencyY_valueChanged(qreal value)
0508 {
0509     if (m_ui.buttonConstrainFrequency->keepAspectRatio()) {
0510         KisSignalsBlocker blocker(m_ui.sliderFrequencyX);
0511         m_ui.sliderFrequencyX->setValue(value);
0512     }
0513     slot_setSizeFromFrequency();
0514     emit sigConfigurationItemChanged();
0515 }
0516 
0517 void KisScreentoneConfigWidget::slot_buttonConstrainFrequency_keepAspectRatioChanged(bool keep)
0518 {
0519     if (keep) {
0520         slot_sliderFrequencyX_valueChanged(m_ui.sliderFrequencyX->value());
0521     }
0522     slot_setSizeFromFrequency();
0523 }
0524 
0525 void KisScreentoneConfigWidget::slot_sliderSizeX_valueChanged(qreal value)
0526 {
0527     if (m_ui.buttonConstrainSize->keepAspectRatio()) {
0528         KisSignalsBlocker blocker(m_ui.sliderSizeY);
0529         m_ui.sliderSizeY->setValue(value);
0530     }
0531     slot_setFrequencyFromSize();
0532     emit sigConfigurationItemChanged();
0533 }
0534 
0535 void KisScreentoneConfigWidget::slot_sliderSizeY_valueChanged(qreal value)
0536 {
0537     if (m_ui.buttonConstrainSize->keepAspectRatio()) {
0538         KisSignalsBlocker blocker(m_ui.sliderSizeX);
0539         m_ui.sliderSizeX->setValue(value);
0540     }
0541     slot_setFrequencyFromSize();
0542     emit sigConfigurationItemChanged();
0543 }
0544 
0545 void KisScreentoneConfigWidget::slot_buttonConstrainSize_keepAspectRatioChanged(bool keep)
0546 {
0547     if (keep) {
0548         slot_sliderSizeX_valueChanged(m_ui.sliderSizeX->value());
0549     }
0550     slot_setFrequencyFromSize();
0551 }
0552 
0553 void KisScreentoneConfigWidget::slot_sliderAlignToPixelGridX_valueChanged(int value)
0554 {
0555     Q_UNUSED(value);
0556     if (m_ui.checkBoxAlignToPixelGrid->isChecked()) {
0557         emit sigConfigurationItemChanged();
0558     }
0559 }
0560 
0561 void KisScreentoneConfigWidget::slot_sliderAlignToPixelGridY_valueChanged(int value)
0562 {
0563     Q_UNUSED(value);
0564     if (m_ui.checkBoxAlignToPixelGrid->isChecked()) {
0565         emit sigConfigurationItemChanged();
0566     }
0567 }
0568 
0569 void KisScreentoneConfigWidget::slot_setFrequencySlidersRanges()
0570 {
0571     KisSignalsBlocker blocker(m_ui.sliderFrequencyX, m_ui.sliderFrequencyY);
0572     const qreal minimumFrequency = m_ui.sliderResolution->value() / maximumCellSize;
0573     const qreal maximumFrequency = m_ui.sliderResolution->value() / minimumCellSize;
0574     m_ui.sliderFrequencyX->setRange(minimumFrequency, maximumFrequency, 2);
0575     m_ui.sliderFrequencyX->setSoftRange(qMax(minimumFrequency, 1.0), qMin(maximumFrequency, 100.0));
0576     m_ui.sliderFrequencyY->setRange(minimumFrequency, maximumFrequency, 2);
0577     m_ui.sliderFrequencyY->setSoftRange(qMax(minimumFrequency, 1.0), qMin(maximumFrequency, 100.0));
0578 }
0579 
0580 void KisScreentoneConfigWidget::slot_setSizeFromFrequency()
0581 {
0582     KisSignalsBlocker blocker(m_ui.sliderSizeX, m_ui.sliderSizeY, m_ui.buttonConstrainSize);
0583     m_ui.sliderSizeX->setValue(m_ui.sliderResolution->value() / m_ui.sliderFrequencyX->value());
0584     m_ui.sliderSizeY->setValue(m_ui.sliderResolution->value() / m_ui.sliderFrequencyY->value());
0585     m_ui.buttonConstrainSize->setKeepAspectRatio(m_ui.buttonConstrainFrequency->keepAspectRatio());
0586 }
0587 
0588 void KisScreentoneConfigWidget::slot_setFrequencyFromSize()
0589 {
0590     KisSignalsBlocker blocker(m_ui.sliderFrequencyX, m_ui.sliderFrequencyY, m_ui.buttonConstrainFrequency);
0591     m_ui.sliderFrequencyX->setValue(m_ui.sliderResolution->value() / m_ui.sliderSizeX->value());
0592     m_ui.sliderFrequencyY->setValue(m_ui.sliderResolution->value() / m_ui.sliderSizeY->value());
0593     m_ui.buttonConstrainFrequency->setKeepAspectRatio(m_ui.buttonConstrainSize->keepAspectRatio());
0594 }