File indexing completed on 2024-05-12 16:01:25
0001 /* 0002 * SPDX-FileCopyrightText: 2016 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_aspect_ratio_locker.h" 0008 0009 #include <QSpinBox> 0010 #include <QDoubleSpinBox> 0011 0012 #include <KoAspectButton.h> 0013 0014 #include "kis_signals_blocker.h" 0015 #include "kis_assert.h" 0016 #include "kis_debug.h" 0017 #include "kis_slider_spin_box.h" 0018 #include "kis_int_parse_spin_box.h" 0019 #include "kis_double_parse_spin_box.h" 0020 #include "kis_double_parse_unit_spin_box.h" 0021 0022 0023 struct SliderWrapper 0024 { 0025 template <class Slider> 0026 SliderWrapper(Slider *slider) 0027 : m_slider(QVariant::fromValue(slider)), 0028 m_object(slider) {} 0029 0030 void setValue(qreal value) { 0031 0032 if (m_slider.canConvert<KisDoubleParseUnitSpinBox*>()) { 0033 m_slider.value<KisDoubleParseUnitSpinBox*>()->changeValue(value); 0034 0035 } else if (m_slider.canConvert<KisDoubleParseSpinBox*>()) { 0036 m_slider.value<KisDoubleParseSpinBox*>()->setValue(value); 0037 0038 } else if (m_slider.canConvert<KisDoubleSliderSpinBox*>()) { 0039 m_slider.value<KisDoubleSliderSpinBox*>()->setValue(value); 0040 0041 } else if (m_slider.canConvert<QDoubleSpinBox*>()) { 0042 m_slider.value<QDoubleSpinBox*>()->setValue(value); 0043 0044 } else if (m_slider.canConvert<KisIntParseSpinBox*>()) { 0045 m_slider.value<KisIntParseSpinBox*>()->setValue(qRound(value)); 0046 0047 } else if (m_slider.canConvert<KisSliderSpinBox*>()) { 0048 m_slider.value<KisSliderSpinBox*>()->setValue(qRound(value)); 0049 0050 } else if (m_slider.canConvert<QSpinBox*>()) { 0051 m_slider.value<QSpinBox*>()->setValue(qRound(value)); 0052 } 0053 } 0054 0055 qreal value() const { 0056 qreal result = 0.0; 0057 0058 if (m_slider.canConvert<KisDoubleParseUnitSpinBox*>()) { 0059 result = m_slider.value<KisDoubleParseUnitSpinBox*>()->value(); 0060 0061 } else if (m_slider.canConvert<KisDoubleParseSpinBox*>()) { 0062 result = m_slider.value<KisDoubleParseSpinBox*>()->value(); 0063 0064 } else if (m_slider.canConvert<KisDoubleSliderSpinBox*>()) { 0065 result = m_slider.value<KisDoubleSliderSpinBox*>()->value(); 0066 0067 } else if (m_slider.canConvert<QDoubleSpinBox*>()) { 0068 result = m_slider.value<QDoubleSpinBox*>()->value(); 0069 0070 } else if (m_slider.canConvert<KisIntParseSpinBox*>()) { 0071 result = m_slider.value<KisIntParseSpinBox*>()->value(); 0072 0073 } else if (m_slider.canConvert<KisSliderSpinBox*>()) { 0074 result = m_slider.value<KisSliderSpinBox*>()->value(); 0075 0076 } else if (m_slider.canConvert<QSpinBox*>()) { 0077 result = m_slider.value<QSpinBox*>()->value(); 0078 0079 } 0080 0081 return result; 0082 } 0083 0084 bool isDragging() const { 0085 bool result = false; 0086 0087 if (m_slider.canConvert<KisSliderSpinBox*>()) { 0088 result = m_slider.value<KisSliderSpinBox*>()->isDragging(); 0089 0090 } else if (m_slider.canConvert<KisDoubleSliderSpinBox*>()) { 0091 result = m_slider.value<KisDoubleSliderSpinBox*>()->isDragging(); 0092 } 0093 0094 return result; 0095 } 0096 0097 void connectDraggingFinished(QObject *receiver, const char *amember) { 0098 0099 if (m_slider.canConvert<KisSliderSpinBox*>()) { 0100 QObject::connect(m_slider.value<KisSliderSpinBox*>(), SIGNAL(draggingFinished()), 0101 receiver, amember); 0102 0103 } else if (m_slider.canConvert<KisDoubleSliderSpinBox*>()) { 0104 QObject::connect(m_slider.value<KisDoubleSliderSpinBox*>(), SIGNAL(draggingFinished()), 0105 receiver, amember); 0106 } 0107 } 0108 0109 QObject* object() const { 0110 return m_object; 0111 } 0112 0113 private: 0114 QVariant m_slider; 0115 QObject *m_object; 0116 }; 0117 0118 struct KisAspectRatioLocker::Private 0119 { 0120 QScopedPointer<SliderWrapper> spinOne; 0121 QScopedPointer<SliderWrapper> spinTwo; 0122 KoAspectButton *aspectButton = 0; 0123 0124 qreal aspectRatio = 1.0; 0125 bool blockUpdatesOnDrag = false; 0126 }; 0127 0128 0129 KisAspectRatioLocker::KisAspectRatioLocker(QObject *parent) 0130 : QObject(parent), 0131 m_d(new Private) 0132 { 0133 } 0134 0135 KisAspectRatioLocker::~KisAspectRatioLocker() 0136 { 0137 } 0138 0139 template <class SpinBoxType> 0140 void KisAspectRatioLocker::connectSpinBoxes(SpinBoxType *spinOne, SpinBoxType *spinTwo, KoAspectButton *aspectButton) 0141 { 0142 m_d->spinOne.reset(new SliderWrapper(spinOne)); 0143 m_d->spinTwo.reset(new SliderWrapper(spinTwo)); 0144 m_d->aspectButton = aspectButton; 0145 0146 if (QVariant::fromValue(spinOne->value()).type() == QVariant::Double) { 0147 connect(spinOne, SIGNAL(valueChanged(qreal)), SLOT(slotSpinOneChanged())); 0148 connect(spinTwo, SIGNAL(valueChanged(qreal)), SLOT(slotSpinTwoChanged())); 0149 } else { 0150 connect(spinOne, SIGNAL(valueChanged(int)), SLOT(slotSpinOneChanged())); 0151 connect(spinTwo, SIGNAL(valueChanged(int)), SLOT(slotSpinTwoChanged())); 0152 } 0153 0154 m_d->spinOne->connectDraggingFinished(this, SLOT(slotSpinDraggingFinished())); 0155 m_d->spinTwo->connectDraggingFinished(this, SLOT(slotSpinDraggingFinished())); 0156 0157 connect(m_d->aspectButton, SIGNAL(keepAspectRatioChanged(bool)), SLOT(slotAspectButtonChanged())); 0158 slotAspectButtonChanged(); 0159 } 0160 0161 template KRITAUI_EXPORT void KisAspectRatioLocker::connectSpinBoxes(QSpinBox *spinOne, QSpinBox *spinTwo, KoAspectButton *aspectButton); 0162 template KRITAUI_EXPORT void KisAspectRatioLocker::connectSpinBoxes(QDoubleSpinBox *spinOne, QDoubleSpinBox *spinTwo, KoAspectButton *aspectButton); 0163 template KRITAUI_EXPORT void KisAspectRatioLocker::connectSpinBoxes(KisSliderSpinBox *spinOne, KisSliderSpinBox *spinTwo, KoAspectButton *aspectButton); 0164 template KRITAUI_EXPORT void KisAspectRatioLocker::connectSpinBoxes(KisDoubleSliderSpinBox *spinOne, KisDoubleSliderSpinBox *spinTwo, KoAspectButton *aspectButton); 0165 template KRITAUI_EXPORT void KisAspectRatioLocker::connectSpinBoxes(KisIntParseSpinBox *spinOne, KisIntParseSpinBox *spinTwo, KoAspectButton *aspectButton); 0166 template KRITAUI_EXPORT void KisAspectRatioLocker::connectSpinBoxes(KisDoubleParseSpinBox *spinOne, KisDoubleParseSpinBox *spinTwo, KoAspectButton *aspectButton); 0167 template KRITAUI_EXPORT void KisAspectRatioLocker::connectSpinBoxes(KisDoubleParseUnitSpinBox *spinOne, KisDoubleParseUnitSpinBox *spinTwo, KoAspectButton *aspectButton); 0168 0169 void KisAspectRatioLocker::slotSpinOneChanged() 0170 { 0171 if (m_d->aspectButton->keepAspectRatio()) { 0172 KisSignalsBlocker b(m_d->spinTwo->object()); 0173 m_d->spinTwo->setValue(m_d->aspectRatio * m_d->spinOne->value()); 0174 } 0175 0176 if (!m_d->blockUpdatesOnDrag || !m_d->spinOne->isDragging()) { 0177 emit sliderValueChanged(); 0178 } 0179 } 0180 0181 void KisAspectRatioLocker::slotSpinTwoChanged() 0182 { 0183 if (m_d->aspectButton->keepAspectRatio()) { 0184 KisSignalsBlocker b(m_d->spinOne->object()); 0185 m_d->spinOne->setValue(m_d->spinTwo->value() / m_d->aspectRatio); 0186 } 0187 0188 if (!m_d->blockUpdatesOnDrag || !m_d->spinTwo->isDragging()) { 0189 emit sliderValueChanged(); 0190 } 0191 } 0192 0193 void KisAspectRatioLocker::slotAspectButtonChanged() 0194 { 0195 if (m_d->aspectButton->keepAspectRatio() && 0196 m_d->spinTwo->value() > 0 && 0197 m_d->spinOne->value() > 0) { 0198 0199 m_d->aspectRatio = qreal(m_d->spinTwo->value()) / m_d->spinOne->value(); 0200 } else { 0201 m_d->aspectRatio = 1.0; 0202 } 0203 0204 if (!m_d->spinTwo->isDragging()) { 0205 emit aspectButtonChanged(); 0206 emit aspectButtonToggled(m_d->aspectButton->keepAspectRatio()); 0207 } 0208 } 0209 0210 void KisAspectRatioLocker::slotSpinDraggingFinished() 0211 { 0212 if (m_d->blockUpdatesOnDrag) { 0213 emit sliderValueChanged(); 0214 } 0215 } 0216 0217 void KisAspectRatioLocker::setBlockUpdateSignalOnDrag(bool value) 0218 { 0219 m_d->blockUpdatesOnDrag = value; 0220 } 0221 0222 void KisAspectRatioLocker::updateAspect() 0223 { 0224 KisSignalsBlocker b(this); 0225 slotAspectButtonChanged(); 0226 }