File indexing completed on 2024-12-01 07:26:15

0001 /*
0002  * SPDX-FileCopyrightText: 2009 Kare Sars <kare dot sars at iki dot fi>
0003  * SPDX-FileCopyrightText: 2014 Gregor Mitsch : port to KDE5 frameworks
0004  * SPDX-FileCopyrightText: 2021 Alexander Stippich <a.stippich@gmx.net>
0005  *
0006  * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007  */
0008 
0009 #include "doubleoption.h"
0010 
0011 #include <QVarLengthArray>
0012 
0013 #include <ksanecore_debug.h>
0014 
0015 static const double FIXED_MAX = 32767.9999;
0016 static const double FIXED_MIN = -32768.0;
0017 static const double MIN_FIXED_STEP = 0.0001;
0018 static const double FIXED_PRECISION = 1.0 / 65536;
0019 
0020 namespace KSaneCore
0021 {
0022 
0023 DoubleOption::DoubleOption(const SANE_Handle handle, const int index)
0024     : BaseOption(handle, index)
0025 {
0026     m_optionType = Option::TypeDouble;
0027 }
0028 
0029 void DoubleOption::readOption()
0030 {
0031     beginOptionReload();
0032 
0033     double step = MIN_FIXED_STEP;
0034     if (m_optDesc->constraint_type == SANE_CONSTRAINT_RANGE) {
0035         step = SANE_UNFIX(m_optDesc->constraint.range->quant);
0036         if (step < MIN_FIXED_STEP) {
0037             step = MIN_FIXED_STEP;
0038         }
0039     }
0040     m_minChange = step;
0041 
0042     endOptionReload();
0043 }
0044 
0045 void DoubleOption::readValue()
0046 {
0047     if (state() == Option::StateHidden) {
0048         return;
0049     }
0050 
0051     // read that current value
0052     QVarLengthArray<unsigned char> data(m_optDesc->size);
0053     SANE_Status status;
0054     SANE_Int res;
0055     status = sane_control_option(m_handle, m_index, SANE_ACTION_GET_VALUE, data.data(), &res);
0056     if (status != SANE_STATUS_GOOD) {
0057         return;
0058     }
0059 
0060     double newValue = SANE_UNFIX(toSANE_Word(data.data()));
0061     if (abs(newValue - m_value) >= FIXED_PRECISION) {
0062         m_value = newValue;
0063         Q_EMIT valueChanged(m_value);
0064     }
0065 }
0066 
0067 bool DoubleOption::setValue(const QVariant &value)
0068 {
0069     if (state() == Option::StateHidden) {
0070         return false;
0071     }
0072     bool ok;
0073     double newValue = value.toDouble(&ok);
0074     if (ok && abs(newValue - m_value) >= m_minChange) {
0075         unsigned char data[4];
0076         SANE_Word fixed;
0077         //qCDebug(KSANE_LOG) <<m_optDesc->name << fVal << "!=" << val;
0078         m_value = newValue;
0079         fixed = SANE_FIX(newValue);
0080         fromSANE_Word(data, fixed);
0081         writeData(data);
0082         Q_EMIT valueChanged(m_value);
0083     }
0084     return ok;
0085 }
0086 
0087 QVariant DoubleOption::minimumValue() const
0088 {
0089     QVariant value;
0090     if (m_optDesc->constraint_type == SANE_CONSTRAINT_RANGE) {
0091         value = SANE_UNFIX(m_optDesc->constraint.range->min);
0092     } else {
0093         value = FIXED_MIN;
0094     }
0095     return value;
0096 }
0097 
0098 QVariant DoubleOption::maximumValue() const
0099 {
0100     QVariant value;
0101     if (m_optDesc->constraint_type == SANE_CONSTRAINT_RANGE) {
0102         value = SANE_UNFIX(m_optDesc->constraint.range->max);
0103     } else {
0104         value = FIXED_MAX;
0105     }
0106     return value;
0107 }
0108 
0109 QVariant DoubleOption::stepValue() const
0110 {
0111     QVariant value;
0112     if (m_optDesc->constraint_type == SANE_CONSTRAINT_RANGE) {
0113         value = SANE_UNFIX(m_optDesc->constraint.range->quant);
0114         /* work around broken backends, the step value must never be zero
0115          * assume a minimum step value of 0.1 */
0116         if (value == 0) {
0117             value = 0.1;
0118         }
0119     } else {
0120         value = MIN_FIXED_STEP;
0121     }
0122     return value;
0123 }
0124 
0125 QVariant DoubleOption::value() const
0126 {
0127     if (state() == Option::StateHidden) {
0128         return QVariant();
0129     }
0130     return QVariant(m_value);
0131 }
0132 
0133 QString DoubleOption::valueAsString() const
0134 {
0135     if (state() == Option::StateHidden) {
0136         return QString();
0137     }
0138     return QString::number(m_value, 'F', 6);
0139 }
0140 
0141 } // namespace KSaneCore
0142 
0143 #include "moc_doubleoption.cpp"