File indexing completed on 2024-05-12 04:33:22

0001 /*
0002  * SPDX-FileCopyrightText: 2007-2011 Kare Sars <kare.sars@iki .fi>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005  */
0006 
0007 // Local includes
0008 #include "labeledfslider.h"
0009 
0010 //KDE includes
0011 
0012 #include <KLocalizedString>
0013 
0014 #define FLOAT_MULTIP 32768.0
0015 #define TO_DOUBLE(v) (static_cast<double>(v) / FLOAT_MULTIP)
0016 #define TO_FIX(v) (static_cast<int>(v * FLOAT_MULTIP))
0017 
0018 namespace KSaneIface
0019 {
0020 
0021 LabeledFSlider::LabeledFSlider(QWidget *parent, const QString &ltext,
0022                                double min, double max, double step)
0023     : KSaneOptionWidget(parent, ltext)
0024 {
0025     initFSlider(min, max, step);
0026 }
0027 
0028 LabeledFSlider::LabeledFSlider(QWidget *parent, KSaneCore::Option *option)
0029     : KSaneOptionWidget(parent, option)
0030 {
0031     double maxValue = option->maximumValue().toDouble();
0032     double minValue = option->minimumValue().toDouble();
0033     double stepValue = option->stepValue().toDouble();
0034     initFSlider(minValue, maxValue , stepValue);
0035 
0036     QString unitSuffix;
0037     KSaneCore::Option::OptionUnit unit = option->valueUnit();
0038     switch (unit) {
0039     case KSaneCore::Option::UnitPixel:
0040         unitSuffix = i18nc("Double numbers. SpinBox parameter unit", " Pixels");
0041         break;
0042     case KSaneCore::Option::UnitBit:
0043         unitSuffix = i18nc("Double numbers. SpinBox parameter unit", " Bits");
0044         break;
0045     case KSaneCore::Option::UnitMilliMeter:
0046         unitSuffix = i18nc("Double numbers. SpinBox parameter unit (Millimeter)", " mm");
0047         break;
0048     case KSaneCore::Option::UnitDPI:
0049         unitSuffix = i18nc("Double numbers. SpinBox parameter unit (Dots Per Inch)", " DPI");
0050         break;
0051     case KSaneCore::Option::UnitPercent:
0052         unitSuffix = i18nc("Double numbers. SpinBox parameter unit (Percentage)", " %");
0053         break;
0054     case KSaneCore::Option::UnitMicroSecond:
0055         unitSuffix = i18nc("Double numbers. SpinBox parameter unit (Microseconds)", " µs");
0056         break;
0057     case KSaneCore::Option::UnitSecond:
0058         unitSuffix = i18nc("SpinBox parameter unit (seconds), float", " s");
0059         break;
0060     default:
0061         unitSuffix = QString();
0062         break;
0063     }
0064     setSuffix(unitSuffix);
0065 
0066     setLabelText(option->title());
0067     setToolTip(option->description());
0068     connect(this, &LabeledFSlider::valueChanged, option, &KSaneCore::Option::setValue);
0069     connect(option, &KSaneCore::Option::valueChanged, this, &LabeledFSlider::setValue);
0070     double value = option->value().toDouble();
0071     setValue(value);
0072 }
0073 
0074 void LabeledFSlider::initFSlider(double minValue, double maxValue, double stepValue)
0075 {
0076     int imin = TO_FIX(minValue);
0077     int imax = TO_FIX(maxValue);
0078     m_istep = TO_FIX(stepValue);
0079     m_fstep = stepValue;
0080     if (m_istep == 0) {
0081         m_istep = 1;
0082         m_fstep = TO_DOUBLE(m_istep);
0083     }
0084 
0085     //std::cout << "min=" << min << ", max=" << max << ", m_fstep="<<m_fstep<<std::endl;
0086     //std::cout << "imin=" << imin << ", imax=" << imax << ", m_istep="<<m_istep<<std::endl;
0087     m_slider = new QSlider(this);
0088     m_slider->setOrientation(Qt::Horizontal);
0089     m_slider->setMinimum(imin);
0090     m_slider->setMaximum(imax);
0091     m_slider->setSingleStep(m_istep);
0092     m_slider->setValue(imin);
0093 
0094     m_spinb = new QDoubleSpinBox(this);
0095     m_spinb->setMinimum(minValue);
0096     m_spinb->setMaximum(maxValue);
0097     m_spinb->setSingleStep(m_fstep);
0098     int decimals = 0;
0099     double tmp_step = m_fstep;
0100     while (tmp_step < 1) {
0101         tmp_step *= 10;
0102         decimals++;
0103         if (decimals > 5) {
0104             break;
0105         }
0106     }
0107     m_spinb->setDecimals(decimals);
0108     m_spinb->setValue(maxValue);
0109     //m_spinb->setMinimumWidth(m_spinb->sizeHint().width()+35);
0110     m_spinb->setMinimumWidth(m_spinb->sizeHint().width());
0111     m_spinb->setAlignment(Qt::AlignRight);
0112     m_spinb->setValue(minValue);
0113 
0114     m_label->setBuddy(m_spinb);
0115 
0116     connect(m_spinb, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, QOverload<double>::of(&LabeledFSlider::syncValues));
0117     connect(m_slider, QOverload<int>::of(&QSlider::valueChanged), this, QOverload<int>::of(&LabeledFSlider::syncValues));
0118     connect(m_slider, &QSlider::sliderReleased, this, &LabeledFSlider::fixValue);
0119 
0120     m_layout->addWidget(m_slider, 0, 2);
0121     m_layout->addWidget(m_spinb, 0, 1);
0122     m_layout->setColumnStretch(1, 0);
0123     m_layout->setColumnStretch(2, 50);
0124     m_layout->activate();
0125 }
0126 
0127 LabeledFSlider::~LabeledFSlider()
0128 {
0129 }
0130 
0131 double LabeledFSlider::value() const
0132 {
0133     return m_spinb->value();
0134 }
0135 
0136 double LabeledFSlider::step() const
0137 {
0138     return m_fstep;
0139 }
0140 
0141 void LabeledFSlider::setSuffix(const QString &text)
0142 {
0143     m_spinb->setSuffix(text);
0144 }
0145 
0146 void LabeledFSlider::setRange(double min, double max)
0147 {
0148     //qCDebug(KSANE_LOG) << "min,max(" << m_spinb->minimum() << " - " << m_spinb->maximum();
0149     //qCDebug(KSANE_LOG) << ") -> (" << min << " - " << max << ")" << std::endl;
0150     int imin = TO_FIX(min);
0151     int imax = TO_FIX(max);
0152     m_slider->setRange(imin, imax);
0153     //std::cout << "fixedmin=" << imin << " fixedmax=" << imax << std::endl;
0154 
0155     m_spinb->setRange(min, max);
0156 }
0157 
0158 void LabeledFSlider::setStep(double step)
0159 {
0160     m_istep = TO_FIX(step);
0161     m_fstep = step;
0162     if (m_istep == 0) {
0163         m_istep = 1;
0164         m_fstep = TO_DOUBLE(m_istep);
0165     }
0166     m_slider->setSingleStep(m_istep);
0167     m_spinb->setSingleStep(m_fstep);
0168 
0169     int decimals = 0;
0170     double tmp_step = m_fstep;
0171     while (tmp_step < 1) {
0172         tmp_step *= 10;
0173         decimals++;
0174         if (decimals > 5) {
0175             break;
0176         }
0177     }
0178     m_spinb->setDecimals(decimals);
0179 }
0180 
0181 void LabeledFSlider::setValue(const QVariant &value)
0182 {
0183     bool ok;
0184     double newValue = value.toDouble(&ok);
0185     if (!ok) {
0186         return;
0187     }
0188     int ivalue = TO_FIX(newValue);
0189 
0190     if (((newValue - m_spinb->value()) > m_fstep) || ((m_spinb->value() - newValue) > m_fstep)) {
0191         m_spinb->setValue(newValue);
0192     } else if (ivalue != m_slider->value()) {
0193         m_slider->setValue(ivalue);
0194     }
0195 }
0196 
0197 void LabeledFSlider::syncValues(int ivalue)
0198 {
0199     double value = TO_DOUBLE(ivalue);
0200     if (((value - m_spinb->value()) > m_fstep) || ((m_spinb->value() - value) > m_fstep)) {
0201         m_spinb->setValue(value);
0202     } else if (ivalue != m_slider->value()) {
0203         m_slider->setValue(ivalue);
0204     } else {
0205         Q_EMIT valueChanged(value);
0206     }
0207 }
0208 
0209 void LabeledFSlider::syncValues(double value)
0210 {
0211     int ivalue = TO_FIX(value);
0212     if (((value - m_spinb->value()) > m_fstep) || ((m_spinb->value() - value) > m_fstep)) {
0213         m_spinb->setValue(value);
0214     } else if (ivalue != m_slider->value()) {
0215         m_slider->setValue(ivalue);
0216     } else {
0217         Q_EMIT valueChanged((float)value);
0218     }
0219 }
0220 
0221 void LabeledFSlider::fixValue()
0222 {
0223     //ensure that the value step is followed also for the m_slider
0224     int rest = (m_slider->value() - m_slider->minimum()) % m_istep;
0225 
0226     if (rest != 0) {
0227         if (rest > (m_istep / 2)) {
0228             m_slider->setValue(m_slider->value() + (m_istep - rest));
0229         } else {
0230             m_slider->setValue(m_slider->value() - rest);
0231         }
0232         m_spinb->setValue(TO_DOUBLE(m_slider->value()));
0233     }
0234 }
0235 
0236 }  // NameSpace KSaneIface
0237 
0238 #include "moc_labeledfslider.cpp"