File indexing completed on 2024-12-22 04:15:32

0001 /*
0002  * This file is part of Krita
0003  *
0004  * SPDX-FileCopyrightText: 2006 Cyrille Berger <cberger@cberger.net>
0005  *
0006  *  SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #include "kis_wdg_pattern.h"
0010 
0011 #include <QLayout>
0012 #include <QLabel>
0013 #include <QSlider>
0014 
0015 #include <KoColor.h>
0016 #include <resources/KoPattern.h>
0017 #include <KisGlobalResourcesInterface.h>
0018 #include <kis_generator_registry.h>
0019 
0020 #include <filter/kis_filter_configuration.h>
0021 #include <kis_pattern_chooser.h>
0022 #include <kis_signals_blocker.h>
0023 #include <KisSpinBoxI18nHelper.h>
0024 
0025 #include "ui_wdgpatternoptions.h"
0026 
0027 KisWdgPattern::KisWdgPattern(QWidget* parent)
0028         : KisConfigWidget(parent)
0029 {
0030     m_widget = new Ui_WdgPatternOptions();
0031     m_widget->setupUi(this);
0032     m_widget->lblPattern->setVisible(false);
0033 
0034     m_widget->sldShearX->setRange(-500, 500, 2);
0035     m_widget->sldShearX->setSoftRange(-100, 100);
0036     m_widget->sldShearX->setSingleStep(1);
0037     m_widget->sldShearX->setValue(0.0);
0038     m_widget->sldShearY->setRange(-500, 500, 2);
0039     m_widget->sldShearY->setSoftRange(-100, 100);
0040     m_widget->sldShearY->setSingleStep(1);
0041     m_widget->sldShearY->setValue(0.0);
0042 
0043     m_widget->spbOffsetX->setRange(-10000, 10000);
0044     m_widget->spbOffsetX->setSoftRange(-500, 500);
0045     m_widget->spbOffsetX->setValue(0);
0046     m_widget->spbOffsetY->setRange(-10000, 10000);
0047     m_widget->spbOffsetY->setSoftRange(-500, 500);
0048     m_widget->spbOffsetY->setValue(0);
0049 
0050     m_widget->spbScaleWidth->setRange(0, 10000, 2);
0051     m_widget->spbScaleWidth->setSoftRange(0, 500);
0052     m_widget->spbScaleWidth->setValue(100.0);
0053     m_widget->spbScaleHeight->setRange(0, 10000, 2);
0054     m_widget->spbScaleHeight->setSoftRange(0, 500);
0055     m_widget->spbScaleHeight->setValue(100.0);
0056 
0057     m_widget->angleSelectorRotationX->setPrefix(i18n("X: "));
0058     m_widget->angleSelectorRotationY->setPrefix(i18n("Y: "));
0059     m_widget->angleSelectorRotationZ->setIncreasingDirection(KisAngleGauge::IncreasingDirection_Clockwise);
0060 
0061     m_widget->container3DRotation->setVisible(false);
0062 
0063     m_widget->sliderAlignToPixelGridX->setRange(1, 20);
0064     m_widget->sliderAlignToPixelGridY->setRange(1, 20);
0065     KisSpinBoxI18nHelper::install(m_widget->sliderAlignToPixelGridX, [](int value) {
0066         // i18n: This is meant to be used in a spinbox so keep the {n} in the text
0067         //       and it will be substituted by the number. The text before will be
0068         //       used as the prefix and the text after as the suffix
0069         return i18ncp("Horizontal pixel grid alignment prefix/suffix for spinboxes in pattern generator", "Every {n} repetition horizontally", "Every {n} repetitions horizontally", value);
0070     });
0071     KisSpinBoxI18nHelper::install(m_widget->sliderAlignToPixelGridY, [](int value) {
0072         // i18n: This is meant to be used in a spinbox so keep the {n} in the text
0073         //       and it will be substituted by the number. The text before will be
0074         //       used as the prefix and the text after as the suffix
0075         return i18ncp("Vertical pixel grid alignment prefix/suffix for spinboxes in pattern generator", "Every {n} repetition vertically", "Every {n} repetitions vertically", value);
0076     });
0077 
0078     connect(m_widget->patternChooser, SIGNAL(resourceSelected(KoResourceSP)), this, SIGNAL(sigConfigurationUpdated()));
0079 
0080     connect(m_widget->sldShearX, SIGNAL(valueChanged(double)), this, SIGNAL(sigConfigurationUpdated()));
0081     connect(m_widget->sldShearY, SIGNAL(valueChanged(double)), this, SIGNAL(sigConfigurationUpdated()));
0082 
0083     connect(m_widget->spbOffsetX, SIGNAL(valueChanged(int)), this, SIGNAL(sigConfigurationUpdated()));
0084     connect(m_widget->spbOffsetY, SIGNAL(valueChanged(int)), this, SIGNAL(sigConfigurationUpdated()));
0085 
0086     connect(m_widget->spbScaleWidth, SIGNAL(valueChanged(double)), this, SLOT(slotWidthChanged(double)));
0087     connect(m_widget->spbScaleHeight, SIGNAL(valueChanged(double)), this, SLOT(slotHeightChanged(double)));
0088     connect(m_widget->btnLockAspectRatio, SIGNAL(keepAspectRatioChanged(bool)), this, SLOT(slotScaleAspectRatioChanged(bool)));
0089 
0090     connect(m_widget->angleSelectorRotationX, SIGNAL(angleChanged(qreal)), this, SIGNAL(sigConfigurationUpdated()));
0091     connect(m_widget->angleSelectorRotationY, SIGNAL(angleChanged(qreal)), this, SIGNAL(sigConfigurationUpdated()));
0092     connect(m_widget->angleSelectorRotationZ, SIGNAL(angleChanged(qreal)), this, SIGNAL(sigConfigurationUpdated()));
0093 
0094     connect(m_widget->checkBoxAlignToPixelGrid, SIGNAL(toggled(bool)), this, SIGNAL(sigConfigurationUpdated()));
0095     connect(m_widget->sliderAlignToPixelGridX, SIGNAL(valueChanged(int)), this, SLOT(slot_sliderAlignToPixelGridX_valueChanged(int)));
0096     connect(m_widget->sliderAlignToPixelGridY, SIGNAL(valueChanged(int)), this, SLOT(slot_sliderAlignToPixelGridY_valueChanged(int)));
0097 }
0098 
0099 KisWdgPattern::~KisWdgPattern()
0100 {
0101     delete m_widget;
0102 }
0103 
0104 
0105 void KisWdgPattern::setConfiguration(const KisPropertiesConfigurationSP config)
0106 {
0107     auto source = KisGlobalResourcesInterface::instance()->source<KoPattern>(ResourceType::Patterns);
0108 
0109     {
0110         KisSignalsBlocker blocker1(m_widget->patternChooser, m_widget->spbOffsetX, m_widget->spbOffsetY,
0111                                    m_widget->spbScaleWidth, m_widget->spbScaleHeight, m_widget->btnLockAspectRatio);
0112         KisSignalsBlocker blocker2(m_widget->sldShearX, m_widget->sldShearY, m_widget->angleSelectorRotationX,
0113                                    m_widget->angleSelectorRotationY, m_widget->angleSelectorRotationZ);
0114         KisSignalsBlocker blocker3(m_widget->checkBoxAlignToPixelGrid, m_widget->sliderAlignToPixelGridX,
0115                                    m_widget->sliderAlignToPixelGridY);
0116 
0117         QString md5sum = config->getString("md5sum");
0118         QString patternName = config->getString("pattern", "Grid01.pat");
0119         KoPatternSP pattern = source.bestMatch(md5sum, "", patternName);
0120         widget()->patternChooser->setCurrentPattern(pattern ? pattern : source.fallbackResource());
0121         m_widget->spbOffsetX->setValue(config->getInt("transform_offset_x", 0));
0122         m_widget->spbOffsetY->setValue(config->getInt("transform_offset_y", 0));
0123 
0124         m_widget->spbScaleWidth->setValue(config->getDouble("transform_scale_x", 1.0) * 100);
0125         m_widget->spbScaleHeight->setValue(config->getDouble("transform_scale_y", 1.0) * 100);
0126         m_widget->btnLockAspectRatio->setKeepAspectRatio(config->getBool("transform_keep_scale_aspect", true));
0127 
0128         m_widget->sldShearX->setValue(config->getDouble("transform_shear_x", 0.0) * 100);
0129         m_widget->sldShearY->setValue(config->getDouble("transform_shear_y", 0.0) * 100);
0130 
0131         widget()->angleSelectorRotationX->setAngle(config->getDouble("transform_rotation_x", 0.0));
0132         widget()->angleSelectorRotationY->setAngle(config->getDouble("transform_rotation_y", 0.0));
0133         widget()->angleSelectorRotationZ->setAngle(config->getDouble("transform_rotation_z", 0.0));
0134 
0135         m_widget->checkBoxAlignToPixelGrid->setChecked(config->getBool("transform_align_to_pixel_grid", false));
0136         m_widget->sliderAlignToPixelGridX->setValue(config->getInt("transform_align_to_pixel_grid_x", 1));
0137         m_widget->sliderAlignToPixelGridY->setValue(config->getInt("transform_align_to_pixel_grid_y", 1));
0138     }
0139     emit sigConfigurationItemChanged();
0140 }
0141 
0142 KisPropertiesConfigurationSP KisWdgPattern::configuration() const
0143 {
0144     KisGeneratorSP generator = KisGeneratorRegistry::instance()->get("pattern");
0145     KisFilterConfigurationSP config = generator->factoryConfiguration(KisGlobalResourcesInterface::instance());
0146 
0147     QVariant v;
0148     KoResourceSP pattern = widget()->patternChooser->currentResource(true);
0149     if (pattern) {
0150         config->setProperty("pattern", pattern->name());
0151         config->setProperty("md5sum", pattern->md5Sum());
0152         config->setProperty("fileName", pattern->filename());
0153     }
0154 
0155     config->setProperty("transform_offset_x", m_widget->spbOffsetX->value());
0156     config->setProperty("transform_offset_y", m_widget->spbOffsetY->value());
0157 
0158     config->setProperty("transform_scale_x", m_widget->spbScaleWidth->value()  / 100);
0159     config->setProperty("transform_scale_y", m_widget->spbScaleHeight->value() / 100);
0160 
0161     config->setProperty("transform_keep_scale_aspect", m_widget->btnLockAspectRatio->keepAspectRatio());
0162 
0163     config->setProperty("transform_shear_x", widget()->sldShearX->value() / 100);
0164     config->setProperty("transform_shear_y", widget()->sldShearY->value() / 100);
0165 
0166     config->setProperty("transform_rotation_x", widget()->angleSelectorRotationX->angle());
0167     config->setProperty("transform_rotation_y", widget()->angleSelectorRotationY->angle());
0168     config->setProperty("transform_rotation_z", widget()->angleSelectorRotationZ->angle());
0169 
0170     config->setProperty("transform_align_to_pixel_grid", m_widget->checkBoxAlignToPixelGrid->isChecked());
0171     config->setProperty("transform_align_to_pixel_grid_x", m_widget->sliderAlignToPixelGridX->value());
0172     config->setProperty("transform_align_to_pixel_grid_y", m_widget->sliderAlignToPixelGridY->value());
0173 
0174     return config;
0175 }
0176 
0177 void KisWdgPattern::slotWidthChanged(double w)
0178 {
0179     if (m_widget->btnLockAspectRatio->keepAspectRatio()) {
0180         KisSignalsBlocker blocker(m_widget->spbScaleHeight);
0181         m_widget->spbScaleHeight->setValue(w);
0182     }
0183     emit sigConfigurationItemChanged();
0184 }
0185 
0186 void KisWdgPattern::slotHeightChanged(double h)
0187 {
0188     if (m_widget->btnLockAspectRatio->keepAspectRatio()) {
0189         KisSignalsBlocker blocker(m_widget->spbScaleWidth);
0190         m_widget->spbScaleWidth->setValue(h);
0191     }
0192     emit sigConfigurationItemChanged();
0193 }
0194 
0195 void KisWdgPattern::slotScaleAspectRatioChanged(bool checked)
0196 {
0197     if (checked && m_widget->spbScaleHeight->value() != m_widget->spbScaleWidth->value()) {
0198         KisSignalsBlocker blocker(m_widget->spbScaleHeight);
0199         m_widget->spbScaleHeight->setValue(m_widget->spbScaleWidth->value());
0200         emit sigConfigurationItemChanged();
0201     }
0202 }
0203 
0204 void KisWdgPattern::slot_sliderAlignToPixelGridX_valueChanged(int value)
0205 {
0206     Q_UNUSED(value);
0207     if (m_widget->checkBoxAlignToPixelGrid->isChecked()) {
0208         emit sigConfigurationItemChanged();
0209     }
0210 }
0211 
0212 void KisWdgPattern::slot_sliderAlignToPixelGridY_valueChanged(int value)
0213 {
0214     Q_UNUSED(value);
0215     if (m_widget->checkBoxAlignToPixelGrid->isChecked()) {
0216         emit sigConfigurationItemChanged();
0217     }
0218 }
0219