File indexing completed on 2024-12-08 07:19:39
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 * 0005 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0006 */ 0007 0008 #include "listoption.h" 0009 0010 #include <QVarLengthArray> 0011 0012 #include <ksanecore_debug.h> 0013 0014 namespace KSaneCore 0015 { 0016 0017 ListOption::ListOption(const SANE_Handle handle, const int index) 0018 : BaseOption(handle, index) 0019 { 0020 m_optionType = Option::TypeValueList; 0021 } 0022 0023 void ListOption::readValue() 0024 { 0025 if (BaseOption::state() == Option::StateHidden) { 0026 return; 0027 } 0028 0029 // read that current value 0030 QVarLengthArray<unsigned char> data(m_optDesc->size); 0031 SANE_Status status; 0032 SANE_Int res; 0033 status = sane_control_option(m_handle, m_index, SANE_ACTION_GET_VALUE, data.data(), &res); 0034 if (status != SANE_STATUS_GOOD) { 0035 return; 0036 } 0037 0038 QVariant newValue; 0039 switch (m_optDesc->type) { 0040 case SANE_TYPE_INT: 0041 newValue = static_cast<int>(toSANE_Word(data.data())); 0042 break; 0043 case SANE_TYPE_FIXED: 0044 newValue = SANE_UNFIX(toSANE_Word(data.data())); 0045 break; 0046 case SANE_TYPE_STRING: 0047 newValue = sane_i18n(reinterpret_cast<char *>(data.data())); 0048 break; 0049 default: 0050 break; 0051 } 0052 0053 if (newValue != m_currentValue) { 0054 m_currentValue = newValue; 0055 Q_EMIT valueChanged(m_currentValue); 0056 } 0057 } 0058 0059 void ListOption::readOption() 0060 { 0061 beginOptionReload(); 0062 countEntries(); 0063 endOptionReload(); 0064 } 0065 0066 QVariantList ListOption::valueList() const 0067 { 0068 int i; 0069 QVariantList list; 0070 list.reserve(m_entriesCount); 0071 0072 switch (m_optDesc->type) { 0073 case SANE_TYPE_INT: 0074 for (i = 1; i <= m_optDesc->constraint.word_list[0]; ++i) { 0075 list << static_cast<int>(m_optDesc->constraint.word_list[i]);; 0076 } 0077 break; 0078 case SANE_TYPE_FIXED: 0079 for (i = 1; i <= m_optDesc->constraint.word_list[0]; ++i) { 0080 list << SANE_UNFIX(m_optDesc->constraint.word_list[i]); 0081 } 0082 break; 0083 case SANE_TYPE_STRING: 0084 i = 0; 0085 while (m_optDesc->constraint.string_list[i] != nullptr) { 0086 list << sane_i18n(m_optDesc->constraint.string_list[i]); 0087 i++; 0088 } 0089 break; 0090 default : 0091 qCDebug(KSANECORE_LOG) << "can not handle type:" << m_optDesc->type; 0092 break; 0093 } 0094 return list; 0095 } 0096 0097 QVariantList ListOption::internalValueList() const 0098 { 0099 int i; 0100 QVariantList list; 0101 list.reserve(m_entriesCount); 0102 0103 switch (m_optDesc->type) { 0104 case SANE_TYPE_INT: 0105 for (i = 1; i <= m_optDesc->constraint.word_list[0]; ++i) { 0106 list << static_cast<int>(m_optDesc->constraint.word_list[i]);; 0107 } 0108 break; 0109 case SANE_TYPE_FIXED: 0110 for (i = 1; i <= m_optDesc->constraint.word_list[0]; ++i) { 0111 list << SANE_UNFIX(m_optDesc->constraint.word_list[i]); 0112 } 0113 break; 0114 case SANE_TYPE_STRING: 0115 i = 0; 0116 while (m_optDesc->constraint.string_list[i] != nullptr) { 0117 list << QString::fromLatin1(m_optDesc->constraint.string_list[i]); 0118 i++; 0119 } 0120 break; 0121 default : 0122 qCDebug(KSANECORE_LOG) << "can not handle type:" << m_optDesc->type; 0123 break; 0124 } 0125 return list; 0126 } 0127 0128 bool ListOption::setValue(const QVariant &value) 0129 { 0130 bool success = false; 0131 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0132 if (static_cast<QMetaType::Type>(value.type()) == QMetaType::QString) { 0133 #else 0134 if (value.userType() == QMetaType::QString) { 0135 #endif 0136 success = setValue(value.toString()); 0137 } else { 0138 success = setValue(value.toDouble()); 0139 } 0140 0141 return success; 0142 } 0143 0144 QVariant ListOption::minimumValue() const 0145 { 0146 QVariant value; 0147 if (BaseOption::state() == Option::StateHidden) { 0148 return value; 0149 } 0150 double dValueMin; 0151 int iValueMin; 0152 switch (m_optDesc->type) { 0153 case SANE_TYPE_INT: 0154 iValueMin = static_cast<int>(m_optDesc->constraint.word_list[1]); 0155 for (int i = 2; i <= m_optDesc->constraint.word_list[0]; i++) { 0156 iValueMin = qMin(static_cast<int>(m_optDesc->constraint.word_list[i]), iValueMin); 0157 } 0158 value = iValueMin; 0159 break; 0160 case SANE_TYPE_FIXED: 0161 dValueMin = SANE_UNFIX(m_optDesc->constraint.word_list[1]); 0162 for (int i = 2; i <= m_optDesc->constraint.word_list[0]; i++) { 0163 dValueMin = qMin(SANE_UNFIX(m_optDesc->constraint.word_list[i]), dValueMin); 0164 } 0165 value = dValueMin; 0166 break; 0167 default: 0168 qCDebug(KSANECORE_LOG) << "can not handle type:" << m_optDesc->type; 0169 return value; 0170 } 0171 return value; 0172 } 0173 0174 QVariant ListOption::value() const 0175 { 0176 if (BaseOption::state() == Option::StateHidden) { 0177 return QVariant(); 0178 } 0179 return m_currentValue; 0180 } 0181 0182 bool ListOption::setValue(double value) 0183 { 0184 unsigned char data[4]; 0185 double tmp; 0186 double minDiff; 0187 int i; 0188 int minIndex = 1; 0189 0190 switch (m_optDesc->type) { 0191 case SANE_TYPE_INT: 0192 tmp = static_cast<double>(m_optDesc->constraint.word_list[minIndex]); 0193 minDiff = qAbs(value - tmp); 0194 for (i = 2; i <= m_optDesc->constraint.word_list[0]; ++i) { 0195 tmp = static_cast<double>(m_optDesc->constraint.word_list[i]); 0196 if (qAbs(value - tmp) < minDiff) { 0197 minDiff = qAbs(value - tmp); 0198 minIndex = i; 0199 } 0200 } 0201 fromSANE_Word(data, m_optDesc->constraint.word_list[minIndex]); 0202 writeData(data); 0203 readValue(); 0204 return (minDiff < 1.0); 0205 case SANE_TYPE_FIXED: 0206 tmp = SANE_UNFIX(m_optDesc->constraint.word_list[minIndex]); 0207 minDiff = qAbs(value - tmp); 0208 for (i = 2; i <= m_optDesc->constraint.word_list[0]; ++i) { 0209 tmp = SANE_UNFIX(m_optDesc->constraint.word_list[i]); 0210 if (qAbs(value - tmp) < minDiff) { 0211 minDiff = qAbs(value - tmp); 0212 minIndex = i; 0213 } 0214 } 0215 fromSANE_Word(data, m_optDesc->constraint.word_list[minIndex]); 0216 writeData(data); 0217 readValue(); 0218 return (minDiff < 1.0); 0219 default: 0220 qCDebug(KSANECORE_LOG) << "can not handle type:" << m_optDesc->type; 0221 break; 0222 } 0223 return false; 0224 } 0225 0226 QString ListOption::valueAsString() const 0227 { 0228 if (BaseOption::state() == Option::StateHidden) { 0229 return QString(); 0230 } 0231 return m_currentValue.toString(); 0232 } 0233 0234 bool ListOption::setValue(const QString &value) 0235 { 0236 if (BaseOption::state() == Option::StateHidden) { 0237 return false; 0238 } 0239 0240 unsigned char data[4]; 0241 void* data_ptr = nullptr; 0242 SANE_Word fixed; 0243 int i; 0244 double d; 0245 bool ok; 0246 QString tmp; 0247 0248 switch (m_optDesc->type) { 0249 case SANE_TYPE_INT: 0250 i = value.toInt(&ok); 0251 if (ok) { 0252 fromSANE_Word(data, i); 0253 data_ptr = data; 0254 } else { 0255 return false; 0256 } 0257 0258 break; 0259 case SANE_TYPE_FIXED: 0260 d = value.toDouble(&ok); 0261 if (ok) { 0262 fixed = SANE_FIX(d); 0263 fromSANE_Word(data, fixed); 0264 data_ptr = data; 0265 } else { 0266 return false; 0267 } 0268 0269 break; 0270 case SANE_TYPE_STRING: 0271 i = 0; 0272 while (m_optDesc->constraint.string_list[i] != nullptr) { 0273 tmp = QString::fromLatin1(m_optDesc->constraint.string_list[i]); 0274 if (value != tmp) { 0275 tmp = sane_i18n(m_optDesc->constraint.string_list[i]); 0276 } 0277 if (value == tmp) { 0278 data_ptr = (void *)m_optDesc->constraint.string_list[i]; 0279 break; 0280 } 0281 i++; 0282 } 0283 if (m_optDesc->constraint.string_list[i] == nullptr) { 0284 return false; 0285 } 0286 break; 0287 default: 0288 qCDebug(KSANECORE_LOG) << "can only handle SANE_TYPE: INT, FIXED and STRING"; 0289 return false; 0290 } 0291 writeData(data_ptr); 0292 0293 readValue(); 0294 return true; 0295 } 0296 0297 void ListOption::countEntries() 0298 { 0299 m_entriesCount = 0; 0300 0301 switch (m_optDesc->type) { 0302 0303 case SANE_TYPE_INT: 0304 case SANE_TYPE_FIXED: 0305 m_entriesCount = m_optDesc->constraint.word_list[0]; 0306 break; 0307 0308 case SANE_TYPE_STRING: 0309 while (m_optDesc->constraint.string_list[m_entriesCount] != nullptr) { 0310 m_entriesCount++; 0311 } 0312 break; 0313 0314 default : 0315 qCDebug(KSANECORE_LOG) << "can not handle type:" << m_optDesc->type; 0316 break; 0317 } 0318 } 0319 0320 Option::OptionState ListOption::state() const 0321 { 0322 if (m_entriesCount <= 1) { 0323 return Option::StateHidden; 0324 } else { 0325 return BaseOption::state(); 0326 } 0327 } 0328 0329 } // namespace KSaneCore 0330 0331 #include "moc_listoption.cpp"