File indexing completed on 2025-02-23 04:09:11

0001 /*
0002  *  dlg_layersize.cc - part of Krita
0003  *
0004  *  SPDX-FileCopyrightText: 2004 Boudewijn Rempt <boud@valdyas.org>
0005  *  SPDX-FileCopyrightText: 2005 Sven Langkamp <sven.langkamp@gmail.com>
0006  *  SPDX-FileCopyrightText: 2013 Juan Palacios <jpalaciosdev@gmail.com>
0007  *
0008  *  SPDX-License-Identifier: GPL-2.0-or-later
0009  */
0010 
0011 #include "dlg_layersize.h"
0012 
0013 #include <KoUnit.h>
0014 #include <kis_config.h>
0015 
0016 #include <klocalizedstring.h>
0017 
0018 #include <kis_document_aware_spin_box_unit_manager.h>
0019 
0020 #include <kis_filter_strategy.h>// XXX: I'm really real bad at arithmetic, let alone math. Here
0021 // be rounding errors. (Boudewijn)
0022 
0023 const QString DlgLayerSize::PARAM_PREFIX = "layersizedlg";
0024 
0025 const QString DlgLayerSize::PARAM_WIDTH_UNIT = DlgLayerSize::PARAM_PREFIX + "_widthunit";
0026 const QString DlgLayerSize::PARAM_HEIGHT_UNIT = DlgLayerSize::PARAM_PREFIX + "_heightunit";
0027 
0028 const QString DlgLayerSize::PARAM_KEEP_AR = DlgLayerSize::PARAM_PREFIX + "_keepar";
0029 const QString DlgLayerSize::PARAM_KEEP_PROP = DlgLayerSize::PARAM_PREFIX + "_keepprop";
0030 
0031 static KisFilterStrategy *lastUsedFilter = nullptr;
0032 
0033 DlgLayerSize::DlgLayerSize(QWidget *  parent, const char * name,
0034                            int width, int height, double resolution)
0035     : KoDialog(parent)
0036     , m_aspectRatio(((double) width) / height)
0037     , m_originalWidth(width)
0038     , m_originalHeight(height)
0039     , m_width(width)
0040     , m_height(height)
0041     , m_resolution(resolution)
0042     , m_keepAspect(true)
0043 {
0044     setCaption(i18n("Layer Size"));
0045     setObjectName(name);
0046     setButtons(Ok | Cancel);
0047     setDefaultButton(Ok);
0048 
0049     m_page = new WdgLayerSize(this);
0050     Q_CHECK_PTR(m_page);
0051     m_page->layout()->setMargin(0);
0052     m_page->setObjectName(name);
0053 
0054     KisConfig cfg(true);
0055 
0056     _widthUnitManager = new KisDocumentAwareSpinBoxUnitManager(this);
0057     _heightUnitManager = new KisDocumentAwareSpinBoxUnitManager(this, KisDocumentAwareSpinBoxUnitManager::PIX_DIR_Y);
0058 
0059     _widthUnitManager->setApparentUnitFromSymbol("px");
0060     _heightUnitManager->setApparentUnitFromSymbol("px");
0061 
0062     m_page->newWidthDouble->setUnitManager(_widthUnitManager);
0063     m_page->newHeightDouble->setUnitManager(_heightUnitManager);
0064     m_page->newWidthDouble->setDecimals(2);
0065     m_page->newHeightDouble->setDecimals(2);
0066     m_page->newWidthDouble->setDisplayUnit(false);
0067     m_page->newHeightDouble->setDisplayUnit(false);
0068 
0069     m_page->newWidthDouble->setValue(width);
0070     m_page->newWidthDouble->setFocus();
0071     m_page->newHeightDouble->setValue(height);
0072 
0073     m_page->filterCmb->setIDList(KisFilterStrategyRegistry::instance()->listKeys());
0074     m_page->filterCmb->setToolTip(KisFilterStrategyRegistry::instance()->formattedDescriptions());
0075     m_page->filterCmb->allowAuto(true);
0076 
0077     if (lastUsedFilter) { // Restore or Init..
0078         m_page->filterCmb->setCurrent(lastUsedFilter->id());
0079     } else {
0080         m_page->filterCmb->setCurrent(KisCmbIDList::AutoOptionID);
0081     }
0082 
0083     m_page->newWidthUnit->setModel(_widthUnitManager);
0084     m_page->newHeightUnit->setModel(_heightUnitManager);
0085 
0086     QString unitw = cfg.readEntry<QString>(PARAM_WIDTH_UNIT, "px");
0087     QString unith = cfg.readEntry<QString>(PARAM_HEIGHT_UNIT, "px");
0088 
0089     _widthUnitManager->setApparentUnitFromSymbol(unitw);
0090     _heightUnitManager->setApparentUnitFromSymbol(unith);
0091 
0092     const int wUnitIndex = _widthUnitManager->getsUnitSymbolList().indexOf(unitw);
0093     const int hUnitIndex = _widthUnitManager->getsUnitSymbolList().indexOf(unith);
0094 
0095     m_page->newWidthUnit->setCurrentIndex(wUnitIndex);
0096     m_page->newHeightUnit->setCurrentIndex(hUnitIndex);
0097 
0098     m_keepAspect = cfg.readEntry(PARAM_KEEP_AR,true);
0099     m_page->aspectRatioBtn->setKeepAspectRatio(m_keepAspect);
0100     m_page->constrainProportionsCkb->setChecked(cfg.readEntry(PARAM_KEEP_PROP,true));
0101 
0102     setMainWidget(m_page);
0103     connect(this, SIGNAL(okClicked()), this, SLOT(accept()));
0104 
0105     connect(m_page->aspectRatioBtn, SIGNAL(keepAspectRatioChanged(bool)), this, SLOT(slotAspectChanged(bool)));
0106     connect(m_page->constrainProportionsCkb, SIGNAL(toggled(bool)), this, SLOT(slotAspectChanged(bool)));
0107 
0108     connect(m_page->newWidthDouble, SIGNAL(valueChangedPt(double)), this, SLOT(slotWidthChanged(double)));
0109     connect(m_page->newHeightDouble, SIGNAL(valueChangedPt(double)), this, SLOT(slotHeightChanged(double)));
0110 
0111     connect(m_page->newWidthUnit, SIGNAL(currentIndexChanged(int)), _widthUnitManager, SLOT(selectApparentUnitFromIndex(int)));
0112     connect(m_page->newHeightUnit, SIGNAL(currentIndexChanged(int)), _heightUnitManager, SLOT(selectApparentUnitFromIndex(int)));
0113     connect(_widthUnitManager, SIGNAL(unitChanged(int)), m_page->newWidthUnit, SLOT(setCurrentIndex(int)));
0114     connect(_heightUnitManager, SIGNAL(unitChanged(int)), m_page->newHeightUnit, SLOT(setCurrentIndex(int)));
0115 
0116     connect(this, &DlgLayerSize::sigDesiredSizeChanged, [this](qint32 width, qint32 height, double){
0117         KisFilterStrategy *filterStrategy = KisFilterStrategyRegistry::instance()->autoFilterStrategy(QSize(m_originalWidth, m_originalHeight), QSize(width, height));
0118         m_page->filterCmb->setAutoHint(filterStrategy->name());
0119     });
0120 }
0121 
0122 DlgLayerSize::~DlgLayerSize()
0123 {
0124 
0125     KisConfig cfg(false);
0126 
0127     cfg.writeEntry<bool>(PARAM_KEEP_AR, m_page->aspectRatioBtn->keepAspectRatio());
0128     cfg.writeEntry<bool>(PARAM_KEEP_PROP, m_page->constrainProportionsCkb->isChecked());
0129 
0130     cfg.writeEntry<QString>(PARAM_WIDTH_UNIT, _widthUnitManager->getApparentUnitSymbol());
0131     cfg.writeEntry<QString>(PARAM_HEIGHT_UNIT, _heightUnitManager->getApparentUnitSymbol());
0132 
0133     delete m_page;
0134 }
0135 
0136 qint32 DlgLayerSize::desiredWidth()
0137 {
0138     return (qint32)m_width;
0139 }
0140 
0141 qint32 DlgLayerSize::desiredHeight()
0142 {
0143     return (qint32)m_height;
0144 }
0145 
0146 KisFilterStrategy *DlgLayerSize::filterType()
0147 {
0148     KoID filterID = m_page->filterCmb->currentItem();
0149 
0150     KisFilterStrategy *filter;
0151     if (filterID == KisCmbIDList::AutoOptionID) {
0152         filter = KisFilterStrategyRegistry::instance()->autoFilterStrategy(QSize(m_originalWidth, m_originalHeight), QSize(desiredWidth(), desiredHeight()));
0153     } else {
0154         filter = KisFilterStrategyRegistry::instance()->value(filterID.id());
0155         lastUsedFilter = filter;  // Save for next time!
0156     }
0157 
0158     return filter;
0159 }
0160 
0161 // SLOTS
0162 
0163 void DlgLayerSize::slotWidthChanged(double w)
0164 {
0165 
0166     //this slot receiv values in pt from the unitspinbox, so just use the resolution.
0167     const double resValue = w*_widthUnitManager->getConversionFactor(KisSpinBoxUnitManager::LENGTH, "px");
0168     m_width = qRound(resValue);
0169 
0170     if (m_keepAspect) {
0171         m_height = qRound(m_width / m_aspectRatio);
0172         m_page->newHeightDouble->blockSignals(true);
0173         m_page->newHeightDouble->changeValue(w / m_aspectRatio);
0174         m_page->newHeightDouble->blockSignals(false);
0175     }
0176 
0177     emit sigDesiredSizeChanged(desiredWidth(), desiredHeight(), m_resolution);
0178 }
0179 
0180 void DlgLayerSize::slotHeightChanged(double h)
0181 {
0182 
0183     //this slot receiv values in pt from the unitspinbox, so just use the resolution.
0184     const double resValue = h*_heightUnitManager->getConversionFactor(KisSpinBoxUnitManager::LENGTH, "px");
0185     m_height = qRound(resValue);
0186 
0187     if (m_keepAspect) {
0188         m_width = qRound(m_height * m_aspectRatio);
0189         m_page->newWidthDouble->blockSignals(true);
0190         m_page->newWidthDouble->changeValue(h * m_aspectRatio);
0191         m_page->newWidthDouble->blockSignals(false);
0192     }
0193 
0194     emit sigDesiredSizeChanged(desiredWidth(), desiredHeight(), m_resolution);
0195 }
0196 
0197 void DlgLayerSize::slotAspectChanged(bool keep)
0198 {
0199     m_page->aspectRatioBtn->blockSignals(true);
0200     m_page->constrainProportionsCkb->blockSignals(true);
0201 
0202     m_page->aspectRatioBtn->setKeepAspectRatio(keep);
0203     m_page->constrainProportionsCkb->setChecked(keep);
0204 
0205     m_page->aspectRatioBtn->blockSignals(false);
0206     m_page->constrainProportionsCkb->blockSignals(false);
0207 
0208     m_keepAspect = keep;
0209 
0210     if (keep) {
0211         // values may be out of sync, so we need to reset it to defaults
0212         m_width = m_originalWidth;
0213         m_height = m_originalHeight;
0214 
0215         updateWidthUIValue(m_width);
0216         updateHeightUIValue(m_height);
0217     }
0218 }
0219 
0220 void DlgLayerSize::updateWidthUIValue(double value)
0221 {
0222     m_page->newWidthDouble->blockSignals(true);
0223     const double resValue = value/_widthUnitManager->getConversionFactor(KisSpinBoxUnitManager::LENGTH, "px");
0224     m_page->newWidthDouble->changeValue(resValue);
0225     m_page->newWidthDouble->blockSignals(false);
0226 }
0227 
0228 void DlgLayerSize::updateHeightUIValue(double value)
0229 {
0230     m_page->newHeightDouble->blockSignals(true);
0231     const double resValue = value/_heightUnitManager->getConversionFactor(KisSpinBoxUnitManager::LENGTH, "px");
0232     m_page->newHeightDouble->changeValue(resValue);
0233     m_page->newHeightDouble->blockSignals(false);
0234 }
0235